summaryrefslogtreecommitdiffstats
path: root/gfx/layers/d3d9/CompositorD3D9.h
blob: 1453d8c7cbc964f780a8a21c34236ccc0320950f (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
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
/* -*- 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_COMPOSITORD3D9_H
#define MOZILLA_GFX_COMPOSITORD3D9_H

#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Point.h"
#include "gfx2DGlue.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/TextureD3D9.h"
#include "DeviceManagerD3D9.h"

class nsWidget;

namespace mozilla {
namespace layers {

class CompositorD3D9 : public Compositor
{
public:
  CompositorD3D9(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget);
  ~CompositorD3D9();

  virtual CompositorD3D9* AsCompositorD3D9() override { return this; }

  virtual bool Initialize(nsCString* const out_failureReason) override;

  virtual TextureFactoryIdentifier
    GetTextureFactoryIdentifier() override;

  virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override;
  virtual int32_t GetMaxTextureSize() const final;

  virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override {}

  virtual already_AddRefed<CompositingRenderTarget>
    CreateRenderTarget(const gfx::IntRect &aRect,
                       SurfaceInitMode aInit) override;

  virtual already_AddRefed<CompositingRenderTarget>
    CreateRenderTargetFromSource(const gfx::IntRect &aRect,
                                 const CompositingRenderTarget *aSource,
                                 const gfx::IntPoint &aSourcePoint) override;

  virtual void SetRenderTarget(CompositingRenderTarget *aSurface) override;
  virtual CompositingRenderTarget* GetCurrentRenderTarget() const override
  {
    return mCurrentRT;
  }

  virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override {}

  virtual void ClearRect(const gfx::Rect& aRect) override;

  virtual void DrawQuad(const gfx::Rect &aRect,
                        const gfx::IntRect &aClipRect,
                        const EffectChain &aEffectChain,
                        gfx::Float aOpacity,
                        const gfx::Matrix4x4& aTransform,
                        const gfx::Rect& aVisibleRect) override;

  virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
                          const gfx::IntRect *aClipRectIn,
                          const gfx::IntRect& aRenderBounds,
                          const nsIntRegion& aOpaqueRegion,
                          gfx::IntRect *aClipRectOut = nullptr,
                          gfx::IntRect *aRenderBoundsOut = nullptr) override;

  virtual void EndFrame() override;

  virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override {}

  virtual void PrepareViewport(const gfx::IntSize& aSize);

  virtual bool SupportsPartialTextureUpdate() override{ return true; }

  virtual bool SupportsEffect(EffectTypes aEffect) override;

#ifdef MOZ_DUMP_PAINTING
  virtual const char* Name() const override { return "Direct3D9"; }
#endif

  virtual LayersBackend GetBackendType() const override {
    return LayersBackend::LAYERS_D3D9;
  }

  IDirect3DDevice9* device() const
  {
    // If the reset counts don't match it means the device was lost and we are
    // in the process of recreating a new one or will be soon.
    // cf. comment in EnsureSwapChain.
    return mDeviceManager && mDeviceResetCount == mDeviceManager->GetDeviceResetCount()
           ? mDeviceManager->device()
           : nullptr;
  }

  /**
   * Returns true if the Compositor is ready to go.
   * D3D9 devices can be awkward and there is a bunch of logic around
   * resetting/recreating devices and swap chains. That is handled by this method.
   * If we don't have a device and swap chain ready for rendering, we will return
   * false and if necessary destroy the device and/or swap chain. We will also
   * schedule another composite so we get another go at rendering, thus we shouldn't
   * miss a composite due to re-creating a device.
   */
  virtual bool Ready() override;

  /**
   * Declare an offset to use when rendering layers. This will be ignored when
   * rendering to a target instead of the screen.
   */
  virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) override
  {
    if (aOffset.x || aOffset.y) {
      NS_RUNTIMEABORT("SetScreenRenderOffset not supported by CompositorD3D9.");
    }
    // If the offset is 0, 0 that's okay.
  }

  virtual already_AddRefed<DataTextureSource>
    CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
private:
  // ensure mSize is up to date with respect to mWidget
  void EnsureSize();
  void SetSamplerForSamplingFilter(gfx::SamplingFilter aSamplingFilter);
  void PaintToTarget();
  void SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture);
  /**
   * Ensure we have a swap chain and it is ready for rendering.
   * Requires mDeviceManger to be non-null.
   * Returns true if we have a working swap chain; false otherwise.
   * If we cannot create or validate the swap chain due to a bad device manager,
   * then the device will be destroyed and set mDeviceManager to null. We will
   * schedule another composite if it is a good idea to try again or we need to
   * recreate the device.
   */
  bool EnsureSwapChain();

  already_AddRefed<IDirect3DTexture9>
  CreateTexture(const gfx::IntRect& aRect,
                const CompositingRenderTarget* aSource,
                const gfx::IntPoint& aSourcePoint);

  /**
   * Complete a mix-blend step at the end of DrawQuad().
   */
  void FinishMixBlend(const gfx::IntRect& aBackdropRect,
                      const gfx::Rect& aBackdropDest,
                      const gfx::Matrix4x4& aBackdropTransform,
                      RefPtr<IDirect3DTexture9> aBackdrop,
                      gfx::CompositionOp aBlendMode);

  /**
   * DeviceManagerD3D9 keeps a count of the number of times its device is
   * reset or recreated. We keep a parallel count (mDeviceResetCount). It
   * is possible that we miss a reset if it is 'caused' by another
   * compositor (for another window). In which case we need to invalidate
   * everything and render it all. This method checks the reset counts
   * match and if not invalidates everything (a long comment on that in
   * the cpp file).
   */
  void CheckResetCount();

  void FailedToResetDevice();

  void ReportFailure(const nsACString &aMsg, HRESULT aCode);

  /* Device manager instance for this compositor */
  RefPtr<DeviceManagerD3D9> mDeviceManager;

  /* Swap chain associated with this compositor */
  RefPtr<SwapChainD3D9> mSwapChain;

  RefPtr<CompositingRenderTargetD3D9> mDefaultRT;
  RefPtr<CompositingRenderTargetD3D9> mCurrentRT;

  LayoutDeviceIntSize mSize;

  uint32_t mDeviceResetCount;
  uint32_t mFailedResetAttempts;
};

}
}

#endif