|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef GFX_LAYERMANAGERD3D9_H |
|
7 #define GFX_LAYERMANAGERD3D9_H |
|
8 |
|
9 #include "Layers.h" |
|
10 |
|
11 #include <windows.h> |
|
12 #include <d3d9.h> |
|
13 |
|
14 #include "gfxContext.h" |
|
15 #include "nsIWidget.h" |
|
16 |
|
17 #include "DeviceManagerD3D9.h" |
|
18 |
|
19 namespace mozilla { |
|
20 namespace layers { |
|
21 |
|
22 class LayerD3D9; |
|
23 class ThebesLayerD3D9; |
|
24 |
|
25 /* |
|
26 * This is the LayerManager used for Direct3D 9. For now this will render on |
|
27 * the main thread. |
|
28 */ |
|
29 class LayerManagerD3D9 : public LayerManager { |
|
30 public: |
|
31 LayerManagerD3D9(nsIWidget *aWidget); |
|
32 virtual ~LayerManagerD3D9(); |
|
33 |
|
34 /* |
|
35 * Initializes the layer manager, this is when the layer manager will |
|
36 * actually access the device and attempt to create the swap chain used |
|
37 * to draw to the window. If this method fails the device cannot be used. |
|
38 * This function is not threadsafe. |
|
39 * |
|
40 * \return True is initialization was succesful, false when it was not. |
|
41 */ |
|
42 bool Initialize(bool force = false); |
|
43 |
|
44 /* |
|
45 * Sets the clipping region for this layer manager. This is important on |
|
46 * windows because using OGL we no longer have GDI's native clipping. Therefor |
|
47 * widget must tell us what part of the screen is being invalidated, |
|
48 * and we should clip to this. |
|
49 * |
|
50 * \param aClippingRegion Region to clip to. Setting an empty region |
|
51 * will disable clipping. |
|
52 */ |
|
53 void SetClippingRegion(const nsIntRegion& aClippingRegion); |
|
54 |
|
55 /* |
|
56 * LayerManager implementation. |
|
57 */ |
|
58 virtual void Destroy(); |
|
59 |
|
60 virtual void BeginTransaction(); |
|
61 |
|
62 virtual void BeginTransactionWithTarget(gfxContext* aTarget); |
|
63 |
|
64 void EndConstruction(); |
|
65 |
|
66 virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT); |
|
67 |
|
68 struct CallbackInfo { |
|
69 DrawThebesLayerCallback Callback; |
|
70 void *CallbackData; |
|
71 }; |
|
72 |
|
73 virtual void EndTransaction(DrawThebesLayerCallback aCallback, |
|
74 void* aCallbackData, |
|
75 EndTransactionFlags aFlags = END_DEFAULT); |
|
76 |
|
77 const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; } |
|
78 |
|
79 void SetRoot(Layer* aLayer); |
|
80 |
|
81 virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) |
|
82 { |
|
83 if (!mDeviceManager) |
|
84 return false; |
|
85 int32_t maxSize = mDeviceManager->GetMaxTextureSize(); |
|
86 return aSize <= gfx::IntSize(maxSize, maxSize); |
|
87 } |
|
88 |
|
89 virtual int32_t GetMaxTextureSize() const |
|
90 { |
|
91 return mDeviceManager->GetMaxTextureSize(); |
|
92 } |
|
93 |
|
94 virtual already_AddRefed<ThebesLayer> CreateThebesLayer(); |
|
95 |
|
96 virtual already_AddRefed<ContainerLayer> CreateContainerLayer(); |
|
97 |
|
98 virtual already_AddRefed<ImageLayer> CreateImageLayer(); |
|
99 |
|
100 virtual already_AddRefed<ColorLayer> CreateColorLayer(); |
|
101 |
|
102 virtual already_AddRefed<CanvasLayer> CreateCanvasLayer(); |
|
103 |
|
104 virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer(); |
|
105 |
|
106 virtual LayersBackend GetBackendType() { return LayersBackend::LAYERS_D3D9; } |
|
107 virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Direct3D 9"); } |
|
108 bool DeviceWasRemoved() { return deviceManager()->DeviceWasRemoved(); } |
|
109 |
|
110 /* |
|
111 * Helper methods. |
|
112 */ |
|
113 void SetClippingEnabled(bool aEnabled); |
|
114 |
|
115 void SetShaderMode(DeviceManagerD3D9::ShaderMode aMode, |
|
116 Layer* aMask, bool aIs2D = true) |
|
117 { mDeviceManager->SetShaderMode(aMode, aMask, aIs2D); } |
|
118 |
|
119 IDirect3DDevice9 *device() const { return mDeviceManager->device(); } |
|
120 DeviceManagerD3D9 *deviceManager() const { return mDeviceManager; } |
|
121 |
|
122 /** |
|
123 * Return pointer to the Nv3DVUtils instance. Re-direct to mDeviceManager. |
|
124 */ |
|
125 Nv3DVUtils *GetNv3DVUtils() { return mDeviceManager ? mDeviceManager->GetNv3DVUtils() : nullptr; } |
|
126 |
|
127 virtual const char* Name() const { return "D3D9"; } |
|
128 |
|
129 void ReportFailure(const nsACString &aMsg, HRESULT aCode); |
|
130 |
|
131 bool CompositingDisabled() { return mCompositingDisabled; } |
|
132 void SetCompositingDisabled(bool aCompositingDisabled) { mCompositingDisabled = aCompositingDisabled; } |
|
133 |
|
134 private: |
|
135 /* Device manager instance for this layer manager */ |
|
136 nsRefPtr<DeviceManagerD3D9> mDeviceManager; |
|
137 |
|
138 /* Swap chain associated with this layer manager */ |
|
139 nsRefPtr<SwapChainD3D9> mSwapChain; |
|
140 |
|
141 /* Widget associated with this layer manager */ |
|
142 nsIWidget *mWidget; |
|
143 |
|
144 /* |
|
145 * Context target, nullptr when drawing directly to our swap chain. |
|
146 */ |
|
147 nsRefPtr<gfxContext> mTarget; |
|
148 |
|
149 /* Callback info for current transaction */ |
|
150 CallbackInfo mCurrentCallbackInfo; |
|
151 |
|
152 /* |
|
153 * Region we're clipping our current drawing to. |
|
154 */ |
|
155 nsIntRegion mClippingRegion; |
|
156 |
|
157 /* |
|
158 * Device reset count at last paint. Whenever this changes, we need to |
|
159 * do a full layer tree update. |
|
160 */ |
|
161 uint32_t mDeviceResetCount; |
|
162 |
|
163 /* |
|
164 * True if we should only be drawing layer contents, not |
|
165 * compositing them to the target. |
|
166 */ |
|
167 bool mCompositingDisabled; |
|
168 |
|
169 /* |
|
170 * Render the current layer tree to the active target. |
|
171 */ |
|
172 void Render(); |
|
173 |
|
174 /* |
|
175 * Setup the pipeline. |
|
176 */ |
|
177 void SetupPipeline(); |
|
178 |
|
179 /* |
|
180 * Copies the content of our backbuffer to the set transaction target. |
|
181 */ |
|
182 void PaintToTarget(); |
|
183 |
|
184 }; |
|
185 |
|
186 /* |
|
187 * General information and tree management for OGL layers. |
|
188 */ |
|
189 class LayerD3D9 |
|
190 { |
|
191 public: |
|
192 LayerD3D9(LayerManagerD3D9 *aManager); |
|
193 |
|
194 virtual LayerD3D9 *GetFirstChildD3D9() { return nullptr; } |
|
195 |
|
196 void SetFirstChild(LayerD3D9 *aParent); |
|
197 |
|
198 virtual Layer* GetLayer() = 0; |
|
199 |
|
200 virtual void RenderLayer() = 0; |
|
201 |
|
202 /** |
|
203 /* This function may be used on device resets to clear all VRAM resources |
|
204 * that a layer might be using. |
|
205 */ |
|
206 virtual void CleanResources() {} |
|
207 |
|
208 IDirect3DDevice9 *device() const { return mD3DManager->device(); } |
|
209 |
|
210 /* Called by the layer manager when it's destroyed */ |
|
211 virtual void LayerManagerDestroyed() {} |
|
212 |
|
213 void ReportFailure(const nsACString &aMsg, HRESULT aCode) { |
|
214 return mD3DManager->ReportFailure(aMsg, aCode); |
|
215 } |
|
216 |
|
217 void SetShaderTransformAndOpacity() |
|
218 { |
|
219 Layer* layer = GetLayer(); |
|
220 const gfx::Matrix4x4& transform = layer->GetEffectiveTransform(); |
|
221 device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4); |
|
222 |
|
223 float opacity[4]; |
|
224 /* |
|
225 * We always upload a 4 component float, but the shader will use only the |
|
226 * first component since it's declared as a 'float'. |
|
227 */ |
|
228 opacity[0] = layer->GetEffectiveOpacity(); |
|
229 device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1); |
|
230 } |
|
231 |
|
232 /* |
|
233 * Returns a texture containing the contents of this |
|
234 * layer. Will try to return an existing texture if possible, or a temporary |
|
235 * one if not. It is the callee's responsibility to release the shader |
|
236 * resource view. Will return null if a texture could not be constructed. |
|
237 * The texture will not be transformed, i.e., it will be in the same coord |
|
238 * space as this. |
|
239 * Any layer that can be used as a mask layer should override this method. |
|
240 * If aSize is non-null and a texture is successfully returned, aSize will |
|
241 * contain the size of the texture. |
|
242 */ |
|
243 virtual already_AddRefed<IDirect3DTexture9> GetAsTexture(gfx::IntSize* aSize) |
|
244 { |
|
245 return nullptr; |
|
246 } |
|
247 |
|
248 protected: |
|
249 LayerManagerD3D9 *mD3DManager; |
|
250 }; |
|
251 |
|
252 /* |
|
253 * RAII helper for locking D3D9 textures. |
|
254 */ |
|
255 class LockTextureRectD3D9 |
|
256 { |
|
257 public: |
|
258 LockTextureRectD3D9(IDirect3DTexture9* aTexture) |
|
259 : mTexture(aTexture) |
|
260 { |
|
261 mLockResult = mTexture->LockRect(0, &mR, nullptr, 0); |
|
262 } |
|
263 |
|
264 ~LockTextureRectD3D9() |
|
265 { |
|
266 mTexture->UnlockRect(0); |
|
267 } |
|
268 |
|
269 bool HasLock() { |
|
270 return SUCCEEDED(mLockResult); |
|
271 } |
|
272 |
|
273 D3DLOCKED_RECT GetLockRect() |
|
274 { |
|
275 return mR; |
|
276 } |
|
277 private: |
|
278 LockTextureRectD3D9 (const LockTextureRectD3D9&); |
|
279 LockTextureRectD3D9& operator= (const LockTextureRectD3D9&); |
|
280 |
|
281 IDirect3DTexture9* mTexture; |
|
282 D3DLOCKED_RECT mR; |
|
283 HRESULT mLockResult; |
|
284 }; |
|
285 |
|
286 } /* layers */ |
|
287 } /* mozilla */ |
|
288 |
|
289 #endif /* GFX_LAYERMANAGERD3D9_H */ |