Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : *
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_RENDERPASSMLGPU_H
8 : #define MOZILLA_GFX_RENDERPASSMLGPU_H
9 :
10 : #include "LayerManagerMLGPU.h"
11 : #include "ShaderDefinitionsMLGPU.h"
12 : #include "SharedBufferMLGPU.h"
13 : #include "StagingBuffer.h"
14 :
15 : namespace mozilla {
16 : namespace layers {
17 :
18 : using namespace mlg;
19 :
20 : class RenderViewMLGPU;
21 :
22 : enum class RenderPassType {
23 : ClearView,
24 : SolidColor,
25 : SingleTexture,
26 : RenderView,
27 : Video,
28 : ComponentAlpha,
29 : Unknown
30 : };
31 :
32 : enum class RenderOrder
33 : {
34 : // Used for all items when not using a depth buffer. Otherwise, used for
35 : // items that may draw transparent pixels.
36 : BackToFront,
37 :
38 : // Only used when the depth buffer is enabled, and only for items that are
39 : // guaranteed to only draw opaque pixels.
40 : FrontToBack
41 : };
42 :
43 : static const uint32_t kInvalidResourceIndex = uint32_t(-1);
44 :
45 0 : struct ItemInfo {
46 : explicit ItemInfo(FrameBuilder* aBuilder,
47 : RenderViewMLGPU* aView,
48 : LayerMLGPU* aLayer,
49 : int32_t aSortOrder,
50 : const gfx::IntRect& aBounds,
51 : Maybe<gfx::Polygon>&& aGeometry);
52 :
53 : // Return true if a layer can be clipped by the vertex shader; false
54 : // otherwise. Any kind of textured mask or non-rectilinear transform
55 : // will cause this to return false.
56 0 : bool HasRectTransformAndClip() const {
57 0 : return rectilinear && !layer->GetMask();
58 : }
59 :
60 : RenderViewMLGPU* view;
61 : LayerMLGPU* layer;
62 : RenderPassType type;
63 : uint32_t layerIndex;
64 : int32_t sortOrder;
65 : gfx::IntRect bounds;
66 : RenderOrder renderOrder;
67 : Maybe<gfx::Polygon> geometry;
68 :
69 : // Set only when the transform is a 2D integer translation.
70 : Maybe<gfx::IntPoint> translation;
71 :
72 : // Set when the item bounds will occlude anything below it.
73 : bool opaque;
74 :
75 : // Set when the item's transform is 2D and rectilinear.
76 : bool rectilinear;
77 : };
78 :
79 : // Base class for anything that can render in a batch to the GPU.
80 : class RenderPassMLGPU
81 : {
82 0 : NS_INLINE_DECL_REFCOUNTING(RenderPassMLGPU)
83 :
84 : public:
85 : static RenderPassType GetPreferredPassType(FrameBuilder* aBuilder,
86 : const ItemInfo& aInfo);
87 :
88 : static RefPtr<RenderPassMLGPU> CreatePass(FrameBuilder* aBuilder,
89 : const ItemInfo& aInfo);
90 :
91 : // Return true if this pass is compatible with the given item, false
92 : // otherwise. This does not guarantee the pass will accept the item,
93 : // but does guarantee we can try.
94 : virtual bool IsCompatible(const ItemInfo& aItem);
95 :
96 : virtual RenderPassType GetType() const = 0;
97 :
98 : // Return true if the layer was compatible with and added to this pass,
99 : // false otherwise.
100 : bool AcceptItem(ItemInfo& aInfo);
101 :
102 : // Prepare constants buffers and textures.
103 : virtual void PrepareForRendering();
104 :
105 : // Execute this render pass to the currently selected surface.
106 : virtual void ExecuteRendering() = 0;
107 :
108 0 : virtual Maybe<MLGBlendState> GetBlendState() const {
109 0 : return Nothing();
110 : }
111 :
112 0 : size_t GetLayerBufferIndex() const {
113 0 : return mLayerBufferIndex;
114 : }
115 0 : Maybe<uint32_t> GetMaskRectBufferIndex() const {
116 0 : return mMaskRectBufferIndex == kInvalidResourceIndex
117 0 : ? Nothing()
118 0 : : Some(mMaskRectBufferIndex);
119 : }
120 :
121 : // Returns true if this pass overlaps the affected region of an item. This
122 : // only ever returns true for transparent items and transparent batches,
123 : // and should not be used otherwise.
124 : bool Intersects(const ItemInfo& aItem);
125 :
126 : // Returns true if pass has been successfully prepared.
127 0 : bool IsPrepared() const {
128 0 : return mPrepared;
129 : }
130 :
131 : protected:
132 : RenderPassMLGPU(FrameBuilder* aBuilder, const ItemInfo& aItem);
133 : virtual ~RenderPassMLGPU();
134 :
135 : // Return true if the item was consumed, false otherwise.
136 : virtual bool AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) = 0;
137 :
138 : protected:
139 : enum class GeometryMode {
140 : Unknown,
141 : UnitQuad,
142 : Polygon
143 : };
144 :
145 : protected:
146 : FrameBuilder* mBuilder;
147 : RefPtr<MLGDevice> mDevice;
148 : size_t mLayerBufferIndex;
149 : size_t mMaskRectBufferIndex;
150 : gfx::IntRegion mAffectedRegion;
151 : bool mPrepared;
152 : };
153 :
154 : // Shader-based render passes execute a draw call, vs. non-shader passes that
155 : // use non-shader APIs (like ClearView).
156 0 : class ShaderRenderPass : public RenderPassMLGPU
157 : {
158 : public:
159 : ShaderRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem);
160 :
161 : // Used by ShaderDefinitions for writing traits.
162 0 : VertexStagingBuffer* GetInstances() {
163 0 : return &mInstances;
164 : }
165 :
166 : bool IsCompatible(const ItemInfo& aItem) override;
167 : void PrepareForRendering() override;
168 : void ExecuteRendering() override;
169 :
170 0 : virtual Maybe<MLGBlendState> GetBlendState() const override{
171 0 : return Some(MLGBlendState::Over);
172 : }
173 :
174 : protected:
175 : // If this batch has a uniform opacity, return it here. Otherwise this should
176 : // return 1.0.
177 : virtual float GetOpacity() const = 0;
178 :
179 : // Set any components of the pipeline that won't be handled by
180 : // ExecuteRendering. This is called only once even if multiple draw calls
181 : // are issued.
182 : virtual void SetupPipeline() = 0;
183 :
184 : protected:
185 : // Set the geometry this pass will use. This must be called by every
186 : // derived constructor. Use GeometryMode::Unknown to pick the default
187 : // behavior: UnitQuads for rectilinear transform+clips, and polygons
188 : // otherwise.
189 : void SetGeometry(const ItemInfo& aItem, GeometryMode aMode);
190 :
191 0 : void SetDefaultGeometry(const ItemInfo& aItem) {
192 0 : SetGeometry(aItem, GeometryMode::Unknown);
193 0 : }
194 :
195 : // Called after PrepareForRendering() has finished. If this returns false,
196 : // PrepareForRendering() will return false.
197 0 : virtual bool OnPrepareBuffers() {
198 0 : return true;
199 : }
200 :
201 : // Prepare the mask/opacity buffer bound in most pixel shaders.
202 : bool SetupPSBuffer0(float aOpacity);
203 :
204 0 : bool HasMask() const {
205 0 : return !!mMask;
206 : }
207 0 : MaskOperation* GetMask() const {
208 0 : return mMask;
209 : }
210 :
211 : protected:
212 : GeometryMode mGeometry;
213 : RefPtr<MaskOperation> mMask;
214 : bool mHasRectTransformAndClip;
215 :
216 : VertexStagingBuffer mInstances;
217 : VertexBufferSection mInstanceBuffer;
218 :
219 : ConstantBufferSection mPSBuffer0;
220 : };
221 :
222 : // This contains various helper functions for building vertices and shader
223 : // inputs for layers.
224 : template <typename Traits>
225 0 : class BatchRenderPass : public ShaderRenderPass
226 : {
227 : public:
228 0 : BatchRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem)
229 0 : : ShaderRenderPass(aBuilder, aItem)
230 0 : {}
231 :
232 : protected:
233 : // It is tricky to determine ahead of time whether or not we'll have enough
234 : // room in our buffers to hold all draw commands for a layer, especially
235 : // since layers can have multiple draw rects. We don't want to draw one rect,
236 : // reject the item, then redraw the same rect again in another batch.
237 : // To deal with this we use a transaction approach and reject the transaction
238 : // if we couldn't add everything.
239 : class Txn {
240 : public:
241 0 : explicit Txn(BatchRenderPass* aPass)
242 : : mPass(aPass),
243 0 : mPrevInstancePos(aPass->mInstances.GetPosition())
244 0 : {}
245 :
246 0 : bool Add(const Traits& aTraits) {
247 0 : if (!AddImpl(aTraits)) {
248 0 : return Fail();
249 : }
250 0 : return true;
251 : }
252 :
253 : // Add an item based on a draw rect, layer, and optional geometry. This is
254 : // defined in RenderPassMLGPU-inl.h, since it needs access to
255 : // ShaderDefinitionsMLGPU-inl.h.
256 : bool AddImpl(const Traits& aTraits);
257 :
258 0 : bool Fail() {
259 0 : MOZ_ASSERT(!mStatus.isSome() || !mStatus.value());
260 0 : mStatus = Some(false);
261 0 : return false;
262 : }
263 :
264 0 : bool Commit() {
265 0 : MOZ_ASSERT(!mStatus.isSome() || !mStatus.value());
266 0 : if (mStatus.isSome()) {
267 0 : return false;
268 : }
269 0 : mStatus = Some(true);
270 0 : return true;
271 : }
272 :
273 0 : ~Txn() {
274 0 : if (!mStatus.isSome() || !mStatus.value()) {
275 0 : mPass->mInstances.RestorePosition(mPrevInstancePos);
276 : }
277 0 : }
278 :
279 : private:
280 : BatchRenderPass* mPass;
281 : VertexStagingBuffer::Position mPrevVertexPos;
282 : VertexStagingBuffer::Position mPrevItemPos;
283 : ConstantStagingBuffer::Position mPrevInstancePos;
284 : Maybe<bool> mStatus;
285 : };
286 : };
287 :
288 : // Shaders which sample from a texture should inherit from this.
289 0 : class TexturedRenderPass : public BatchRenderPass<TexturedTraits>
290 : {
291 : public:
292 : explicit TexturedRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem);
293 :
294 : protected:
295 : // Add a set of draw rects based on a visible region. The texture size and
296 : // scaling factor are used to compute uv-coordinates.
297 : //
298 : // The origin is the offset from the draw rect to the layer bounds. You can
299 : // also think of it as the translation from layer space into texture space,
300 : // pre-scaling. For example, ImageLayers use the texture bounds as their
301 : // draw rect, so the origin will be (0, 0). ContainerLayer intermediate
302 : // surfaces, on the other hand, are relative to the target offset of the
303 : // layer. In all cases the visible region may be partially occluded, so
304 : // knowing the true origin is important.
305 0 : bool AddItems(Txn& aTxn,
306 : const ItemInfo& aInfo,
307 : const nsIntRegion& aDrawRects,
308 : const gfx::IntPoint& aDestOrigin,
309 : const gfx::IntSize& aTextureSize,
310 : const Maybe<gfx::Size>& aScale = Nothing())
311 : {
312 0 : gfx::Point origin(aDestOrigin);
313 0 : for (auto iter = aDrawRects.RectIter(); !iter.Done(); iter.Next()) {
314 0 : gfx::Rect drawRect = gfx::Rect(iter.Get());
315 0 : if (!AddItem(aTxn, aInfo, drawRect, origin, aTextureSize, aScale)) {
316 0 : return false;
317 : }
318 : }
319 0 : return true;
320 : }
321 :
322 : private:
323 : // Add a draw instance to the given destination rect. Texture coordinates
324 : // are built from the given texture size, optional scaling factor, and
325 : // texture origin relative to the draw rect. This will ultimately call
326 : // AddClippedItem, potentially clipping the draw rect if needed.
327 : bool AddItem(Txn& aTxn,
328 : const ItemInfo& aInfo,
329 : const gfx::Rect& aDrawRect,
330 : const gfx::Point& aDestOrigin,
331 : const gfx::IntSize& aTextureSize,
332 : const Maybe<gfx::Size>& aTextureScale = Nothing());
333 :
334 : // Add an item that has gone through any necessary clipping already. This
335 : // is the final destination for handling textured items.
336 : bool AddClippedItem(Txn& aTxn,
337 : const ItemInfo& aInfo,
338 : const gfx::Rect& aDrawRect,
339 : const gfx::Point& aDestOrigin,
340 : const gfx::IntSize& aTextureSize,
341 : const Maybe<gfx::Size>& aScale);
342 :
343 : protected:
344 : TextureFlags mTextureFlags;
345 : };
346 :
347 : // This is only available when MLGDevice::CanUseClearView returns true.
348 0 : class ClearViewPass final : public RenderPassMLGPU
349 : {
350 : public:
351 : ClearViewPass(FrameBuilder* aBuilder, const ItemInfo& aItem);
352 :
353 : bool IsCompatible(const ItemInfo& aItem) override;
354 : void ExecuteRendering() override;
355 :
356 0 : RenderPassType GetType() const override {
357 0 : return RenderPassType::ClearView;
358 : }
359 :
360 : private:
361 : bool AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) override;
362 :
363 : private:
364 : // Note: Not a RefPtr since this would create a cycle.
365 : RenderViewMLGPU* mView;
366 : gfx::Color mColor;
367 : nsTArray<gfx::IntRect> mRects;
368 : };
369 :
370 : // SolidColorPass is used when ClearViewPass is not available, or when
371 : // the layer has masks, or subpixel or complex transforms.
372 0 : class SolidColorPass final : public BatchRenderPass<ColorTraits>
373 : {
374 : public:
375 : explicit SolidColorPass(FrameBuilder* aBuilder, const ItemInfo& aItem);
376 :
377 0 : RenderPassType GetType() const override {
378 0 : return RenderPassType::SolidColor;
379 : }
380 :
381 : private:
382 : bool AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) override;
383 : void SetupPipeline() override;
384 : float GetOpacity() const override;
385 : };
386 :
387 0 : class SingleTexturePass final : public TexturedRenderPass
388 : {
389 : public:
390 : explicit SingleTexturePass(FrameBuilder* aBuilder, const ItemInfo& aItem);
391 :
392 0 : RenderPassType GetType() const override {
393 0 : return RenderPassType::SingleTexture;
394 : }
395 :
396 : private:
397 : bool AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) override;
398 : void SetupPipeline() override;
399 0 : float GetOpacity() const override {
400 0 : return mOpacity;
401 : }
402 : Maybe<MLGBlendState> GetBlendState() const override;
403 :
404 : private:
405 : RefPtr<TextureSource> mTexture;
406 : gfx::SamplingFilter mFilter;
407 : float mOpacity;
408 : };
409 :
410 0 : class ComponentAlphaPass final : public TexturedRenderPass
411 : {
412 : public:
413 : explicit ComponentAlphaPass(FrameBuilder* aBuilder, const ItemInfo& aItem);
414 :
415 0 : RenderPassType GetType() const override {
416 0 : return RenderPassType::ComponentAlpha;
417 : }
418 :
419 : private:
420 : bool AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) override;
421 : void SetupPipeline() override;
422 : float GetOpacity() const override;
423 0 : Maybe<MLGBlendState> GetBlendState() const override {
424 0 : return Some(MLGBlendState::ComponentAlpha);
425 : }
426 :
427 : private:
428 : PaintedLayerMLGPU* mAssignedLayer;
429 : RefPtr<TextureSource> mTextureOnBlack;
430 : RefPtr<TextureSource> mTextureOnWhite;
431 : };
432 :
433 0 : class VideoRenderPass final : public TexturedRenderPass
434 : {
435 : public:
436 : explicit VideoRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem);
437 :
438 0 : RenderPassType GetType() const override {
439 0 : return RenderPassType::Video;
440 : }
441 :
442 : private:
443 : bool AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) override;
444 : void SetupPipeline() override;
445 0 : float GetOpacity() const override {
446 0 : return mOpacity;
447 : }
448 :
449 : private:
450 : RefPtr<TextureHost> mHost;
451 : RefPtr<TextureSource> mTexture;
452 : gfx::SamplingFilter mFilter;
453 : float mOpacity;
454 : };
455 :
456 0 : class RenderViewPass final : public TexturedRenderPass
457 : {
458 : public:
459 : RenderViewPass(FrameBuilder* aBuilder, const ItemInfo& aItem);
460 :
461 0 : RenderPassType GetType() const override {
462 0 : return RenderPassType::RenderView;
463 : }
464 :
465 : private:
466 : bool AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) override;
467 : void SetupPipeline() override;
468 : bool OnPrepareBuffers() override;
469 : float GetOpacity() const override;
470 : bool PrepareBlendState();
471 :
472 : private:
473 : ConstantBufferSection mBlendConstants;
474 : ContainerLayerMLGPU* mAssignedLayer;
475 : RefPtr<MLGRenderTarget> mSource;
476 : // Note: we don't use RefPtr here since that would cause a cycle. RenderViews
477 : // and RenderPasses are both scoped to the frame anyway.
478 : RenderViewMLGPU* mParentView;
479 : gfx::IntRect mBackdropCopyRect;
480 : Maybe<gfx::CompositionOp> mBlendMode;
481 : };
482 :
483 : } // namespace layers
484 : } // namespace mozilla
485 :
486 : #endif
|