|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
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 |
|
7 #include "mozilla/layers/PLayerTransaction.h" |
|
8 |
|
9 #include "gfxWindowsSurface.h" |
|
10 #include "gfxWindowsPlatform.h" |
|
11 #include "SurfaceStream.h" |
|
12 #include "SharedSurfaceGL.h" |
|
13 #include "GLContext.h" |
|
14 #include "CanvasLayerD3D9.h" |
|
15 |
|
16 using namespace mozilla::gfx; |
|
17 using namespace mozilla::gl; |
|
18 |
|
19 namespace mozilla { |
|
20 namespace layers { |
|
21 |
|
22 CanvasLayerD3D9::CanvasLayerD3D9(LayerManagerD3D9 *aManager) |
|
23 : CanvasLayer(aManager, nullptr) |
|
24 , LayerD3D9(aManager) |
|
25 , mDataIsPremultiplied(false) |
|
26 , mNeedsYFlip(false) |
|
27 , mHasAlpha(true) |
|
28 { |
|
29 mImplData = static_cast<LayerD3D9*>(this); |
|
30 aManager->deviceManager()->mLayersWithResources.AppendElement(this); |
|
31 } |
|
32 |
|
33 CanvasLayerD3D9::~CanvasLayerD3D9() |
|
34 { |
|
35 if (mD3DManager) { |
|
36 mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this); |
|
37 } |
|
38 } |
|
39 |
|
40 void |
|
41 CanvasLayerD3D9::Initialize(const Data& aData) |
|
42 { |
|
43 NS_ASSERTION(mDrawTarget == nullptr, "BasicCanvasLayer::Initialize called twice!"); |
|
44 |
|
45 if (aData.mDrawTarget) { |
|
46 mDrawTarget = aData.mDrawTarget; |
|
47 mNeedsYFlip = false; |
|
48 mDataIsPremultiplied = true; |
|
49 } else if (aData.mGLContext) { |
|
50 mGLContext = aData.mGLContext; |
|
51 NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen."); |
|
52 mDataIsPremultiplied = aData.mIsGLAlphaPremult; |
|
53 mNeedsYFlip = true; |
|
54 } else { |
|
55 NS_ERROR("CanvasLayer created without mGLContext or mDrawTarget?"); |
|
56 } |
|
57 |
|
58 mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); |
|
59 |
|
60 CreateTexture(); |
|
61 } |
|
62 |
|
63 void |
|
64 CanvasLayerD3D9::UpdateSurface() |
|
65 { |
|
66 if (!IsDirty() && mTexture) |
|
67 return; |
|
68 Painted(); |
|
69 |
|
70 if (!mTexture) { |
|
71 CreateTexture(); |
|
72 |
|
73 if (!mTexture) { |
|
74 NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!"); |
|
75 return; |
|
76 } |
|
77 } |
|
78 |
|
79 RefPtr<SourceSurface> surface; |
|
80 |
|
81 if (mGLContext) { |
|
82 SharedSurface_GL* surf = mGLContext->RequestFrame(); |
|
83 if (!surf) |
|
84 return; |
|
85 |
|
86 SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf); |
|
87 surface = shareSurf->GetData(); |
|
88 } else { |
|
89 surface = mDrawTarget->Snapshot(); |
|
90 } |
|
91 |
|
92 // WebGL reads entire surface. |
|
93 LockTextureRectD3D9 textureLock(mTexture); |
|
94 if (!textureLock.HasLock()) { |
|
95 NS_WARNING("Failed to lock CanvasLayer texture."); |
|
96 return; |
|
97 } |
|
98 |
|
99 D3DLOCKED_RECT rect = textureLock.GetLockRect(); |
|
100 IntSize boundsSize(mBounds.width, mBounds.height); |
|
101 RefPtr<DrawTarget> rectDt = Factory::CreateDrawTargetForData(BackendType::CAIRO, |
|
102 (uint8_t*)rect.pBits, |
|
103 boundsSize, |
|
104 rect.Pitch, |
|
105 SurfaceFormat::B8G8R8A8); |
|
106 |
|
107 Rect drawRect(0, 0, surface->GetSize().width, surface->GetSize().height); |
|
108 rectDt->DrawSurface(surface, drawRect, drawRect, |
|
109 DrawSurfaceOptions(), DrawOptions(1.0F, CompositionOp::OP_SOURCE)); |
|
110 rectDt->Flush(); |
|
111 } |
|
112 |
|
113 Layer* |
|
114 CanvasLayerD3D9::GetLayer() |
|
115 { |
|
116 return this; |
|
117 } |
|
118 |
|
119 void |
|
120 CanvasLayerD3D9::RenderLayer() |
|
121 { |
|
122 FirePreTransactionCallback(); |
|
123 UpdateSurface(); |
|
124 if (mD3DManager->CompositingDisabled()) { |
|
125 return; |
|
126 } |
|
127 FireDidTransactionCallback(); |
|
128 |
|
129 if (!mTexture) |
|
130 return; |
|
131 |
|
132 /* |
|
133 * We flip the Y axis here, note we can only do this because we are in |
|
134 * CULL_NONE mode! |
|
135 */ |
|
136 |
|
137 ShaderConstantRect quad(0, 0, mBounds.width, mBounds.height); |
|
138 if (mNeedsYFlip) { |
|
139 quad.mHeight = (float)-mBounds.height; |
|
140 quad.mY = (float)mBounds.height; |
|
141 } |
|
142 |
|
143 device()->SetVertexShaderConstantF(CBvLayerQuad, quad, 1); |
|
144 |
|
145 SetShaderTransformAndOpacity(); |
|
146 |
|
147 if (mHasAlpha) { |
|
148 mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, GetMaskLayer()); |
|
149 } else { |
|
150 mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER, GetMaskLayer()); |
|
151 } |
|
152 |
|
153 if (mFilter == GraphicsFilter::FILTER_NEAREST) { |
|
154 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); |
|
155 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); |
|
156 } |
|
157 if (!mDataIsPremultiplied) { |
|
158 device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); |
|
159 device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); |
|
160 } |
|
161 device()->SetTexture(0, mTexture); |
|
162 device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); |
|
163 if (!mDataIsPremultiplied) { |
|
164 device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); |
|
165 device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); |
|
166 } |
|
167 if (mFilter == GraphicsFilter::FILTER_NEAREST) { |
|
168 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); |
|
169 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); |
|
170 } |
|
171 } |
|
172 |
|
173 void |
|
174 CanvasLayerD3D9::CleanResources() |
|
175 { |
|
176 if (mD3DManager->deviceManager()->HasDynamicTextures()) { |
|
177 // In this case we have a texture in POOL_DEFAULT |
|
178 mTexture = nullptr; |
|
179 } |
|
180 } |
|
181 |
|
182 void |
|
183 CanvasLayerD3D9::LayerManagerDestroyed() |
|
184 { |
|
185 mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this); |
|
186 mD3DManager = nullptr; |
|
187 } |
|
188 |
|
189 void |
|
190 CanvasLayerD3D9::CreateTexture() |
|
191 { |
|
192 HRESULT hr; |
|
193 if (mD3DManager->deviceManager()->HasDynamicTextures()) { |
|
194 hr = device()->CreateTexture(mBounds.width, mBounds.height, 1, D3DUSAGE_DYNAMIC, |
|
195 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, |
|
196 getter_AddRefs(mTexture), nullptr); |
|
197 } else { |
|
198 // D3DPOOL_MANAGED is fine here since we require Dynamic Textures for D3D9Ex |
|
199 // devices. |
|
200 hr = device()->CreateTexture(mBounds.width, mBounds.height, 1, 0, |
|
201 D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, |
|
202 getter_AddRefs(mTexture), nullptr); |
|
203 } |
|
204 if (FAILED(hr)) { |
|
205 mD3DManager->ReportFailure(NS_LITERAL_CSTRING("CanvasLayerD3D9::CreateTexture() failed"), |
|
206 hr); |
|
207 return; |
|
208 } |
|
209 } |
|
210 |
|
211 } /* namespace layers */ |
|
212 } /* namespace mozilla */ |