Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
6 #include "CanvasLayerD3D10.h"
8 #include "../d3d9/Nv3DVUtils.h"
9 #include "gfxWindowsSurface.h"
10 #include "gfxWindowsPlatform.h"
11 #include "SurfaceStream.h"
12 #include "SharedSurfaceANGLE.h"
13 #include "SharedSurfaceGL.h"
14 #include "gfxContext.h"
15 #include "GLContext.h"
16 #include "gfxPrefs.h"
18 using namespace mozilla::gl;
19 using namespace mozilla::gfx;
21 namespace mozilla {
22 namespace layers {
24 CanvasLayerD3D10::CanvasLayerD3D10(LayerManagerD3D10 *aManager)
25 : CanvasLayer(aManager, nullptr)
26 , LayerD3D10(aManager)
27 , mDataIsPremultiplied(false)
28 , mNeedsYFlip(false)
29 , mHasAlpha(true)
30 {
31 mImplData = static_cast<LayerD3D10*>(this);
32 }
34 CanvasLayerD3D10::~CanvasLayerD3D10()
35 {
36 }
38 void
39 CanvasLayerD3D10::Initialize(const Data& aData)
40 {
41 NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
43 if (aData.mGLContext) {
44 mGLContext = aData.mGLContext;
45 NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen.");
46 mDataIsPremultiplied = aData.mIsGLAlphaPremult;
47 mNeedsYFlip = true;
49 GLScreenBuffer* screen = mGLContext->Screen();
50 SurfaceStreamType streamType =
51 SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
52 screen->PreserveBuffer());
54 SurfaceFactory_GL* factory = nullptr;
55 if (!gfxPrefs::WebGLForceLayersReadback()) {
56 if (mGLContext->IsANGLE()) {
57 factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext,
58 device(),
59 screen->Caps());
60 }
61 }
63 if (factory) {
64 screen->Morph(factory, streamType);
65 }
66 } else if (aData.mDrawTarget) {
67 mDrawTarget = aData.mDrawTarget;
68 mNeedsYFlip = false;
69 mDataIsPremultiplied = true;
70 void *texture = mDrawTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE);
72 if (texture) {
73 mTexture = static_cast<ID3D10Texture2D*>(texture);
75 NS_ASSERTION(!aData.mGLContext,
76 "CanvasLayer can't have both DrawTarget and WebGLContext/Surface");
78 mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
79 device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
80 return;
81 }
83 // XXX we should store mDrawTarget and use it directly in UpdateSurface,
84 // bypassing Thebes
85 mSurface = mDrawTarget->Snapshot();
86 } else {
87 NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
88 }
90 mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
91 mIsD2DTexture = false;
93 // Create a texture in case we need to readback.
94 CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
95 desc.Usage = D3D10_USAGE_DYNAMIC;
96 desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
98 HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
99 if (FAILED(hr)) {
100 NS_WARNING("Failed to create texture for CanvasLayer!");
101 return;
102 }
104 device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mUploadSRView));
105 }
107 void
108 CanvasLayerD3D10::UpdateSurface()
109 {
110 if (!IsDirty())
111 return;
112 Painted();
114 if (mDrawTarget) {
115 mDrawTarget->Flush();
116 } else if (mIsD2DTexture) {
117 return;
118 }
120 if (!mTexture) {
121 return;
122 }
124 if (mGLContext) {
125 SharedSurface_GL* surf = mGLContext->RequestFrame();
126 if (!surf) {
127 return;
128 }
130 switch (surf->Type()) {
131 case SharedSurfaceType::EGLSurfaceANGLE: {
132 SharedSurface_ANGLEShareHandle* shareSurf = SharedSurface_ANGLEShareHandle::Cast(surf);
134 mSRView = shareSurf->GetSRV();
135 return;
136 }
137 case SharedSurfaceType::Basic: {
138 SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf);
139 // WebGL reads entire surface.
140 D3D10_MAPPED_TEXTURE2D map;
142 HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
144 if (FAILED(hr)) {
145 NS_WARNING("Failed to map CanvasLayer texture.");
146 return;
147 }
149 DataSourceSurface* frameData = shareSurf->GetData();
150 // Scope for DrawTarget, so it's destroyed before Unmap.
151 {
152 IntSize boundsSize(mBounds.width, mBounds.height);
153 RefPtr<DrawTarget> mapDt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
154 (uint8_t*)map.pData,
155 boundsSize,
156 map.RowPitch,
157 SurfaceFormat::B8G8R8A8);
159 Rect drawRect(0, 0, frameData->GetSize().width, frameData->GetSize().height);
160 mapDt->DrawSurface(frameData, drawRect, drawRect,
161 DrawSurfaceOptions(), DrawOptions(1.0F, CompositionOp::OP_SOURCE));
162 mapDt->Flush();
163 }
165 mTexture->Unmap(0);
166 mSRView = mUploadSRView;
167 break;
168 }
170 default:
171 MOZ_CRASH("Unhandled SharedSurfaceType.");
172 }
173 } else if (mSurface) {
174 D3D10_MAPPED_TEXTURE2D map;
175 HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
177 if (FAILED(hr)) {
178 NS_WARNING("Failed to lock CanvasLayer texture.");
179 return;
180 }
182 RefPtr<DrawTarget> destTarget =
183 Factory::CreateDrawTargetForD3D10Texture(mTexture,
184 SurfaceFormat::R8G8B8A8);
185 Rect r(Point(0, 0), ToRect(mBounds).Size());
186 destTarget->DrawSurface(mSurface, r, r, DrawSurfaceOptions(),
187 DrawOptions(1.0F, CompositionOp::OP_SOURCE));
189 mTexture->Unmap(0);
190 mSRView = mUploadSRView;
191 }
192 }
194 Layer*
195 CanvasLayerD3D10::GetLayer()
196 {
197 return this;
198 }
200 void
201 CanvasLayerD3D10::RenderLayer()
202 {
203 FirePreTransactionCallback();
204 UpdateSurface();
205 FireDidTransactionCallback();
207 if (!mTexture)
208 return;
210 nsIntRect visibleRect = mVisibleRegion.GetBounds();
212 SetEffectTransformAndOpacity();
214 uint8_t shaderFlags = 0;
215 shaderFlags |= LoadMaskTexture();
216 shaderFlags |= mDataIsPremultiplied
217 ? SHADER_PREMUL : SHADER_NON_PREMUL | SHADER_RGBA;
218 shaderFlags |= mHasAlpha ? SHADER_RGBA : SHADER_RGB;
219 shaderFlags |= mFilter == GraphicsFilter::FILTER_NEAREST
220 ? SHADER_POINT : SHADER_LINEAR;
221 ID3D10EffectTechnique* technique = SelectShader(shaderFlags);
223 if (mSRView) {
224 effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(mSRView);
225 }
227 effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
228 ShaderConstantRectD3D10(
229 (float)mBounds.x,
230 (float)mBounds.y,
231 (float)mBounds.width,
232 (float)mBounds.height)
233 );
235 if (mNeedsYFlip) {
236 effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
237 ShaderConstantRectD3D10(
238 0,
239 1.0f,
240 1.0f,
241 -1.0f)
242 );
243 }
245 technique->GetPassByIndex(0)->Apply(0);
246 device()->Draw(4, 0);
248 if (mNeedsYFlip) {
249 effect()->GetVariableByName("vTextureCoords")->AsVector()->
250 SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
251 }
252 }
254 } /* namespace layers */
255 } /* namespace mozilla */