summaryrefslogtreecommitdiffstats
path: root/gfx/layers/d3d9
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/d3d9')
-rw-r--r--gfx/layers/d3d9/CompositorD3D9.cpp1045
-rw-r--r--gfx/layers/d3d9/CompositorD3D9.h189
-rw-r--r--gfx/layers/d3d9/DeviceManagerD3D9.cpp966
-rw-r--r--gfx/layers/d3d9/DeviceManagerD3D9.h353
-rwxr-xr-xgfx/layers/d3d9/LayerManagerD3D9Shaders.h1631
-rw-r--r--gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl242
-rw-r--r--gfx/layers/d3d9/Nv3DVUtils.cpp148
-rw-r--r--gfx/layers/d3d9/Nv3DVUtils.h86
-rw-r--r--gfx/layers/d3d9/ReadbackLayerD3D9.h34
-rw-r--r--gfx/layers/d3d9/TextureD3D9.cpp1218
-rw-r--r--gfx/layers/d3d9/TextureD3D9.h433
-rw-r--r--gfx/layers/d3d9/genshaders.sh35
12 files changed, 6380 insertions, 0 deletions
diff --git a/gfx/layers/d3d9/CompositorD3D9.cpp b/gfx/layers/d3d9/CompositorD3D9.cpp
new file mode 100644
index 000000000..0f7e942c1
--- /dev/null
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -0,0 +1,1045 @@
+/* -*- 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/. */
+
+#include "CompositorD3D9.h"
+#include "LayerManagerD3D9Shaders.h"
+#include "gfxWindowsPlatform.h"
+#include "nsIWidget.h"
+#include "mozilla/layers/ImageHost.h"
+#include "mozilla/layers/ContentHost.h"
+#include "mozilla/layers/Effects.h"
+#include "nsWindowsHelpers.h"
+#include "Nv3DVUtils.h"
+#include "gfxFailure.h"
+#include "mozilla/layers/LayerManagerComposite.h"
+#include "gfxPrefs.h"
+#include "gfxCrashReporterUtils.h"
+#include "gfxUtils.h"
+#include "mozilla/gfx/DeviceManagerDx.h"
+#include "mozilla/layers/CompositorBridgeParent.h"
+#include "mozilla/widget/WinCompositorWidget.h"
+#include "D3D9SurfaceImage.h"
+
+namespace mozilla {
+namespace layers {
+
+using namespace mozilla::gfx;
+
+CompositorD3D9::CompositorD3D9(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget)
+ : Compositor(aWidget, aParent)
+ , mDeviceResetCount(0)
+ , mFailedResetAttempts(0)
+{
+}
+
+CompositorD3D9::~CompositorD3D9()
+{
+ mSwapChain = nullptr;
+ mDeviceManager = nullptr;
+}
+
+bool
+CompositorD3D9::Initialize(nsCString* const out_failureReason)
+{
+ ScopedGfxFeatureReporter reporter("D3D9 Layers");
+
+ mDeviceManager = DeviceManagerD3D9::Get();
+ if (!mDeviceManager) {
+ *out_failureReason = "FEATURE_FAILURE_D3D9_DEVICE_MANAGER";
+ return false;
+ }
+
+ mSwapChain = mDeviceManager->CreateSwapChain(mWidget->AsWindows()->GetHwnd());
+ if (!mSwapChain) {
+ *out_failureReason = "FEATURE_FAILURE_D3D9_SWAP_CHAIN";
+ return false;
+ }
+
+ if (!mWidget->InitCompositor(this)) {
+ *out_failureReason = "FEATURE_FAILURE_D3D9_INIT_COMPOSITOR";
+ return false;
+ }
+
+ reporter.SetSuccessful();
+
+ return true;
+}
+
+TextureFactoryIdentifier
+CompositorD3D9::GetTextureFactoryIdentifier()
+{
+ TextureFactoryIdentifier ident;
+ ident.mMaxTextureSize = GetMaxTextureSize();
+ ident.mParentBackend = LayersBackend::LAYERS_D3D9;
+ ident.mParentProcessType = XRE_GetProcessType();
+ ident.mSupportsComponentAlpha = SupportsEffect(EffectTypes::COMPONENT_ALPHA);
+ return ident;
+}
+
+bool
+CompositorD3D9::CanUseCanvasLayerForSize(const IntSize &aSize)
+{
+ int32_t maxTextureSize = GetMaxTextureSize();
+
+ if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) {
+ return false;
+ }
+
+ return true;
+}
+
+int32_t
+CompositorD3D9::GetMaxTextureSize() const
+{
+ return mDeviceManager ? mDeviceManager->GetMaxTextureSize() : INT32_MAX;
+}
+
+already_AddRefed<DataTextureSource>
+CompositorD3D9::CreateDataTextureSource(TextureFlags aFlags)
+{
+ return MakeAndAddRef<DataTextureSourceD3D9>(SurfaceFormat::UNKNOWN, this, aFlags);
+}
+
+already_AddRefed<CompositingRenderTarget>
+CompositorD3D9::CreateRenderTarget(const gfx::IntRect &aRect,
+ SurfaceInitMode aInit)
+{
+ MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");
+
+ if (aRect.width * aRect.height == 0) {
+ return nullptr;
+ }
+
+ if (!mDeviceManager) {
+ return nullptr;
+ }
+
+ RefPtr<IDirect3DTexture9> texture;
+ HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
+ D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+ D3DPOOL_DEFAULT, getter_AddRefs(texture),
+ nullptr);
+ if (FAILED(hr)) {
+ ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTarget: Failed to create texture"),
+ hr);
+ return nullptr;
+ }
+
+ return MakeAndAddRef<CompositingRenderTargetD3D9>(texture, aInit, aRect);
+}
+
+already_AddRefed<IDirect3DTexture9>
+CompositorD3D9::CreateTexture(const gfx::IntRect& aRect,
+ const CompositingRenderTarget* aSource,
+ const gfx::IntPoint& aSourcePoint)
+{
+ MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");
+
+ if (aRect.width * aRect.height == 0) {
+ return nullptr;
+ }
+
+ if (!mDeviceManager) {
+ return nullptr;
+ }
+
+ RefPtr<IDirect3DTexture9> texture;
+ HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
+ D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+ D3DPOOL_DEFAULT, getter_AddRefs(texture),
+ nullptr);
+ if (FAILED(hr)) {
+ ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTargetFromSource: Failed to create texture"),
+ hr);
+ return nullptr;
+ }
+
+ if (aSource) {
+ RefPtr<IDirect3DSurface9> sourceSurface =
+ static_cast<const CompositingRenderTargetD3D9*>(aSource)->GetD3D9Surface();
+
+ RefPtr<IDirect3DSurface9> destSurface;
+ hr = texture->GetSurfaceLevel(0, getter_AddRefs(destSurface));
+ if (FAILED(hr)) {
+ NS_WARNING("Failed to get texture surface level for dest.");
+ }
+
+ if (sourceSurface && destSurface) {
+ RECT sourceRect;
+ sourceRect.left = aSourcePoint.x;
+ sourceRect.right = aSourcePoint.x + aRect.width;
+ sourceRect.top = aSourcePoint.y;
+ sourceRect.bottom = aSourcePoint.y + aRect.height;
+ RECT destRect;
+ destRect.left = 0;
+ destRect.right = aRect.width;
+ destRect.top = 0;
+ destRect.bottom = aRect.height;
+
+ // copy the source to the dest
+ hr = device()->StretchRect(sourceSurface,
+ &sourceRect,
+ destSurface,
+ &destRect,
+ D3DTEXF_NONE);
+ if (FAILED(hr)) {
+ ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTargetFromSource: Failed to update texture"),
+ hr);
+ }
+ }
+ }
+
+ return texture.forget();
+}
+
+already_AddRefed<CompositingRenderTarget>
+CompositorD3D9::CreateRenderTargetFromSource(const gfx::IntRect &aRect,
+ const CompositingRenderTarget *aSource,
+ const gfx::IntPoint &aSourcePoint)
+{
+ RefPtr<IDirect3DTexture9> texture = CreateTexture(aRect, aSource, aSourcePoint);
+
+ if (!texture) {
+ return nullptr;
+ }
+
+ return MakeAndAddRef<CompositingRenderTargetD3D9>(texture,
+ INIT_MODE_NONE,
+ aRect);
+}
+
+void
+CompositorD3D9::SetRenderTarget(CompositingRenderTarget *aRenderTarget)
+{
+ MOZ_ASSERT(aRenderTarget && mDeviceManager);
+ RefPtr<CompositingRenderTargetD3D9> oldRT = mCurrentRT;
+ mCurrentRT = static_cast<CompositingRenderTargetD3D9*>(aRenderTarget);
+ mCurrentRT->BindRenderTarget(device());
+ PrepareViewport(mCurrentRT->GetSize());
+}
+
+static DeviceManagerD3D9::ShaderMode
+ShaderModeForEffectType(EffectTypes aEffectType, gfx::SurfaceFormat aFormat)
+{
+ switch (aEffectType) {
+ case EffectTypes::SOLID_COLOR:
+ return DeviceManagerD3D9::SOLIDCOLORLAYER;
+ case EffectTypes::RENDER_TARGET:
+ return DeviceManagerD3D9::RGBALAYER;
+ case EffectTypes::RGB:
+ if (aFormat == SurfaceFormat::B8G8R8A8 || aFormat == SurfaceFormat::R8G8B8A8)
+ return DeviceManagerD3D9::RGBALAYER;
+ return DeviceManagerD3D9::RGBLAYER;
+ case EffectTypes::YCBCR:
+ return DeviceManagerD3D9::YCBCRLAYER;
+ }
+
+ MOZ_CRASH("GFX: Bad effect type");
+}
+
+void
+CompositorD3D9::ClearRect(const gfx::Rect& aRect)
+{
+ D3DRECT rect;
+ rect.x1 = aRect.X();
+ rect.y1 = aRect.Y();
+ rect.x2 = aRect.XMost();
+ rect.y2 = aRect.YMost();
+
+ device()->Clear(1, &rect, D3DCLEAR_TARGET,
+ 0x00000000, 0, 0);
+}
+
+void
+CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
+ const gfx::IntRect &aClipRect,
+ const EffectChain &aEffectChain,
+ gfx::Float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const gfx::Rect& aVisibleRect)
+{
+ if (!mDeviceManager) {
+ return;
+ }
+
+ IDirect3DDevice9* d3d9Device = device();
+ MOZ_ASSERT(d3d9Device, "We should be able to get a device now");
+
+ MOZ_ASSERT(mCurrentRT, "No render target");
+ d3d9Device->SetVertexShaderConstantF(CBmLayerTransform, &aTransform._11, 4);
+
+ IntPoint origin = mCurrentRT->GetOrigin();
+ float renderTargetOffset[] = { float(origin.x), float(origin.y), 0, 0 };
+ d3d9Device->SetVertexShaderConstantF(CBvRenderTargetOffset,
+ renderTargetOffset,
+ 1);
+ d3d9Device->SetVertexShaderConstantF(CBvLayerQuad,
+ ShaderConstantRect(aRect.x,
+ aRect.y,
+ aRect.width,
+ aRect.height),
+ 1);
+
+ if (aEffectChain.mPrimaryEffect->mType != EffectTypes::SOLID_COLOR) {
+ float opacity[4];
+ /*
+ * We always upload a 4 component float, but the shader will use only the
+ * first component since it's declared as a 'float'.
+ */
+ opacity[0] = aOpacity;
+ d3d9Device->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
+ }
+
+ bool isPremultiplied = true;
+
+ MaskType maskType = MaskType::MaskNone;
+
+ if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
+ maskType = MaskType::Mask;
+ }
+
+ gfx::Rect backdropDest;
+ gfx::IntRect backdropRect;
+ gfx::Matrix4x4 backdropTransform;
+ RefPtr<IDirect3DTexture9> backdropTexture;
+ gfx::CompositionOp blendMode = gfx::CompositionOp::OP_OVER;
+
+ if (aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE]) {
+ EffectBlendMode *blendEffect =
+ static_cast<EffectBlendMode*>(aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE].get());
+ blendMode = blendEffect->mBlendMode;
+
+ // Pixel Shader Model 2.0 is too limited to perform blending in the same way
+ // as Direct3D 11 - there are too many instructions, and we don't have
+ // configurable shaders (as we do with OGL) that would avoid a huge shader
+ // matrix.
+ //
+ // Instead, we use a multi-step process for blending on D3D9:
+ // (1) Capture the backdrop into a temporary surface.
+ // (2) Render the effect chain onto the backdrop, with OP_SOURCE.
+ // (3) Capture the backdrop again into another surface - these are our source pixels.
+ // (4) Perform a final blend step using software.
+ // (5) Blit the blended result back to the render target.
+ if (BlendOpIsMixBlendMode(blendMode)) {
+ backdropRect = ComputeBackdropCopyRect(
+ aRect, aClipRect, aTransform, &backdropTransform, &backdropDest);
+
+ // If this fails, don't set a blend op.
+ backdropTexture = CreateTexture(backdropRect, mCurrentRT, backdropRect.TopLeft());
+ if (!backdropTexture) {
+ blendMode = gfx::CompositionOp::OP_OVER;
+ }
+ }
+ }
+
+ RECT scissor;
+ scissor.left = aClipRect.x;
+ scissor.right = aClipRect.XMost();
+ scissor.top = aClipRect.y;
+ scissor.bottom = aClipRect.YMost();
+ d3d9Device->SetScissorRect(&scissor);
+
+ uint32_t maskTexture = 0;
+ switch (aEffectChain.mPrimaryEffect->mType) {
+ case EffectTypes::SOLID_COLOR:
+ {
+ // output color is premultiplied, so we need to adjust all channels.
+ Color layerColor =
+ static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
+ float color[4];
+ color[0] = layerColor.r * layerColor.a * aOpacity;
+ color[1] = layerColor.g * layerColor.a * aOpacity;
+ color[2] = layerColor.b * layerColor.a * aOpacity;
+ color[3] = layerColor.a * aOpacity;
+
+ d3d9Device->SetPixelShaderConstantF(CBvColor, color, 1);
+
+ maskTexture = mDeviceManager
+ ->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER, maskType);
+ }
+ break;
+ case EffectTypes::RENDER_TARGET:
+ case EffectTypes::RGB:
+ {
+ TexturedEffect* texturedEffect =
+ static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
+
+ Rect textureCoords = texturedEffect->mTextureCoords;
+ d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
+ ShaderConstantRect(
+ textureCoords.x,
+ textureCoords.y,
+ textureCoords.width,
+ textureCoords.height),
+ 1);
+
+ SetSamplerForSamplingFilter(texturedEffect->mSamplingFilter);
+
+ TextureSourceD3D9* source = texturedEffect->mTexture->AsSourceD3D9();
+ d3d9Device->SetTexture(0, source->GetD3D9Texture());
+
+ maskTexture = mDeviceManager
+ ->SetShaderMode(ShaderModeForEffectType(aEffectChain.mPrimaryEffect->mType,
+ texturedEffect->mTexture->GetFormat()),
+ maskType);
+
+ isPremultiplied = texturedEffect->mPremultiplied;
+ }
+ break;
+ case EffectTypes::YCBCR:
+ {
+ EffectYCbCr* ycbcrEffect =
+ static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
+
+ SetSamplerForSamplingFilter(SamplingFilter::LINEAR);
+
+ Rect textureCoords = ycbcrEffect->mTextureCoords;
+ d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
+ ShaderConstantRect(
+ textureCoords.x,
+ textureCoords.y,
+ textureCoords.width,
+ textureCoords.height),
+ 1);
+
+ const int Y = 0, Cb = 1, Cr = 2;
+ TextureSource* source = ycbcrEffect->mTexture;
+
+ if (!source) {
+ NS_WARNING("No texture to composite");
+ return;
+ }
+
+ if (!source->GetSubSource(Y) || !source->GetSubSource(Cb) || !source->GetSubSource(Cr)) {
+ // This can happen if we failed to upload the textures, most likely
+ // because of unsupported dimensions (we don't tile YCbCr textures).
+ return;
+ }
+
+
+ float* yuvToRgb = gfxUtils::Get4x3YuvColorMatrix(ycbcrEffect->mYUVColorSpace);
+ d3d9Device->SetPixelShaderConstantF(CBmYuvColorMatrix, yuvToRgb, 3);
+
+ TextureSourceD3D9* sourceY = source->GetSubSource(Y)->AsSourceD3D9();
+ TextureSourceD3D9* sourceCb = source->GetSubSource(Cb)->AsSourceD3D9();
+ TextureSourceD3D9* sourceCr = source->GetSubSource(Cr)->AsSourceD3D9();
+
+
+ MOZ_ASSERT(sourceY->GetD3D9Texture());
+ MOZ_ASSERT(sourceCb->GetD3D9Texture());
+ MOZ_ASSERT(sourceCr->GetD3D9Texture());
+
+ /*
+ * Send 3d control data and metadata
+ */
+ if (mDeviceManager->GetNv3DVUtils()) {
+ Nv_Stereo_Mode mode;
+ switch (source->AsSourceD3D9()->GetStereoMode()) {
+ case StereoMode::LEFT_RIGHT:
+ mode = NV_STEREO_MODE_LEFT_RIGHT;
+ break;
+ case StereoMode::RIGHT_LEFT:
+ mode = NV_STEREO_MODE_RIGHT_LEFT;
+ break;
+ case StereoMode::BOTTOM_TOP:
+ mode = NV_STEREO_MODE_BOTTOM_TOP;
+ break;
+ case StereoMode::TOP_BOTTOM:
+ mode = NV_STEREO_MODE_TOP_BOTTOM;
+ break;
+ case StereoMode::MONO:
+ mode = NV_STEREO_MODE_MONO;
+ break;
+ }
+
+ // Send control data even in mono case so driver knows to leave stereo mode.
+ mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
+
+ if (source->AsSourceD3D9()->GetStereoMode() != StereoMode::MONO) {
+ mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
+
+ RefPtr<IDirect3DSurface9> renderTarget;
+ d3d9Device->GetRenderTarget(0, getter_AddRefs(renderTarget));
+ mDeviceManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)aRect.width,
+ (unsigned int)aRect.height,
+ (HANDLE)(sourceY->GetD3D9Texture()),
+ (HANDLE)(renderTarget));
+ }
+ }
+
+ // Linear scaling is default here, adhering to mFilter is difficult since
+ // presumably even with point filtering we'll still want chroma upsampling
+ // to be linear. In the current approach we can't.
+ device()->SetTexture(Y, sourceY->GetD3D9Texture());
+ device()->SetTexture(Cb, sourceCb->GetD3D9Texture());
+ device()->SetTexture(Cr, sourceCr->GetD3D9Texture());
+ maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, maskType);
+ }
+ break;
+ case EffectTypes::COMPONENT_ALPHA:
+ {
+ MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
+ EffectComponentAlpha* effectComponentAlpha =
+ static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
+ TextureSourceD3D9* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D9();
+ TextureSourceD3D9* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D9();
+
+ Rect textureCoords = effectComponentAlpha->mTextureCoords;
+ d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
+ ShaderConstantRect(
+ textureCoords.x,
+ textureCoords.y,
+ textureCoords.width,
+ textureCoords.height),
+ 1);
+
+ SetSamplerForSamplingFilter(effectComponentAlpha->mSamplingFilter);
+
+ maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS1, maskType);
+ SetMask(aEffectChain, maskTexture);
+ d3d9Device->SetTexture(0, sourceOnBlack->GetD3D9Texture());
+ d3d9Device->SetTexture(1, sourceOnWhite->GetD3D9Texture());
+ d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+ d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
+ d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+
+ maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS2, maskType);
+ SetMask(aEffectChain, maskTexture);
+ d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+ d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+ d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+
+ // Restore defaults
+ d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+ d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+ d3d9Device->SetTexture(1, nullptr);
+ }
+ return;
+ default:
+ NS_WARNING("Unknown shader type");
+ return;
+ }
+
+ SetMask(aEffectChain, maskTexture);
+
+ if (BlendOpIsMixBlendMode(blendMode)) {
+ // Use SOURCE instead of OVER to get the original source pixels without
+ // having to render to another intermediate target.
+ d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
+ }
+ if (!isPremultiplied) {
+ d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+ }
+
+ d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+
+ // Restore defaults.
+ if (BlendOpIsMixBlendMode(blendMode)) {
+ d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+ }
+ if (!isPremultiplied) {
+ d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+ }
+
+ // Final pass - if mix-blending, do it now that we have the backdrop and
+ // source textures.
+ if (BlendOpIsMixBlendMode(blendMode)) {
+ FinishMixBlend(
+ backdropRect,
+ backdropDest,
+ backdropTransform,
+ backdropTexture,
+ blendMode);
+ }
+}
+
+void
+CompositorD3D9::SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture)
+{
+ EffectMask *maskEffect =
+ static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
+ if (!maskEffect) {
+ return;
+ }
+
+ TextureSourceD3D9 *source = maskEffect->mMaskTexture->AsSourceD3D9();
+
+ device()->SetTexture(aMaskTexture, source->GetD3D9Texture());
+
+ const gfx::Matrix4x4& maskTransform = maskEffect->mMaskTransform;
+ NS_ASSERTION(maskTransform.Is2D(), "How did we end up with a 3D transform here?!");
+ Rect bounds = Rect(Point(), Size(maskEffect->mSize));
+ bounds = maskTransform.As2D().TransformBounds(bounds);
+
+ device()->SetVertexShaderConstantF(DeviceManagerD3D9::sMaskQuadRegister,
+ ShaderConstantRect(bounds.x,
+ bounds.y,
+ bounds.width,
+ bounds.height),
+ 1);
+}
+
+/**
+ * In the next few methods we call |mParent->InvalidateRemoteLayers()| - that has
+ * a few uses - if our device or swap chain is not ready, it causes us to try
+ * to render again, that means we keep trying to get a good device and swap
+ * chain and don't block the main thread (which we would if we kept trying in
+ * a busy loop because this is likely to happen in a sync transaction).
+ * If we had to recreate our device, then we have new textures and we
+ * need to reupload everything (not just what is currently invalid) from the
+ * client side. That means we need to invalidate everything on the client.
+ * If we just reset and didn't need to recreate, then we don't need to reupload
+ * our textures, but we do need to redraw the whole window, which means we still
+ * need to invalidate everything.
+ * Currently we probably do this complete invalidation too much. But it is better
+ * to do that than to miss an invalidation which would result in a black layer
+ * (or multiple layers) until the user moves the mouse. The unnecessary invalidtion
+ * only happens when the device is reset, so that should be pretty rare and when
+ * other things are happening so the user does not expect super performance.
+ */
+
+bool
+CompositorD3D9::EnsureSwapChain()
+{
+ MOZ_ASSERT(mDeviceManager, "Don't call EnsureSwapChain without a device manager");
+
+ if (!mSwapChain) {
+ mSwapChain = mDeviceManager->CreateSwapChain(mWidget->AsWindows()->GetHwnd());
+ // We could not create a swap chain, return false
+ if (!mSwapChain) {
+ // Check the state of the device too
+ DeviceManagerState state = mDeviceManager->VerifyReadyForRendering();
+ if (state == DeviceMustRecreate) {
+ mDeviceManager = nullptr;
+ }
+ mParent->InvalidateRemoteLayers();
+ return false;
+ }
+ }
+
+ // We have a swap chain, lets initialise it
+ DeviceManagerState state = mSwapChain->PrepareForRendering();
+ if (state == DeviceOK) {
+ mFailedResetAttempts = 0;
+ return true;
+ }
+ // Swap chain could not be initialised, handle the failure
+ if (state == DeviceMustRecreate) {
+ mDeviceManager = nullptr;
+ mSwapChain = nullptr;
+ }
+ mParent->InvalidateRemoteLayers();
+ return false;
+}
+
+void
+CompositorD3D9::CheckResetCount()
+{
+ if (mDeviceResetCount != mDeviceManager->GetDeviceResetCount()) {
+ mParent->InvalidateRemoteLayers();
+ }
+ mDeviceResetCount = mDeviceManager->GetDeviceResetCount();
+}
+
+bool
+CompositorD3D9::Ready()
+{
+ if (mDeviceManager) {
+ if (EnsureSwapChain()) {
+ // We don't need to call VerifyReadyForRendering because that is
+ // called by mSwapChain->PrepareForRendering() via EnsureSwapChain().
+ CheckResetCount();
+ return true;
+ }
+ return false;
+ }
+
+ NS_ASSERTION(!mCurrentRT && !mDefaultRT,
+ "Shouldn't have any render targets around, they must be released before our device");
+ mSwapChain = nullptr;
+
+ mDeviceManager = DeviceManagerD3D9::Get();
+ if (!mDeviceManager) {
+ FailedToResetDevice();
+ mParent->InvalidateRemoteLayers();
+ return false;
+ }
+ if (EnsureSwapChain()) {
+ CheckResetCount();
+ return true;
+ }
+ return false;
+}
+
+void
+CompositorD3D9::FailedToResetDevice() {
+ mFailedResetAttempts += 1;
+ // 10 is a totally arbitrary number that we may want to increase or decrease
+ // depending on how things behave in the wild.
+ if (mFailedResetAttempts > 10) {
+ mFailedResetAttempts = 0;
+ DeviceManagerDx::Get()->NotifyD3D9DeviceReset();
+ gfxCriticalNote << "[D3D9] Unable to get a working D3D9 Compositor";
+ }
+}
+
+void
+CompositorD3D9::BeginFrame(const nsIntRegion& aInvalidRegion,
+ const IntRect *aClipRectIn,
+ const IntRect& aRenderBounds,
+ const nsIntRegion& aOpaqueRegion,
+ IntRect *aClipRectOut,
+ IntRect *aRenderBoundsOut)
+{
+ MOZ_ASSERT(mDeviceManager && mSwapChain);
+
+ mDeviceManager->SetupRenderState();
+
+ EnsureSize();
+
+ device()->Clear(0, nullptr, D3DCLEAR_TARGET, 0x00000000, 0, 0);
+ device()->BeginScene();
+
+ if (aClipRectOut) {
+ *aClipRectOut = IntRect(0, 0, mSize.width, mSize.height);
+ }
+ if (aRenderBoundsOut) {
+ *aRenderBoundsOut = IntRect(0, 0, mSize.width, mSize.height);
+ }
+
+ RECT r;
+ if (aClipRectIn) {
+ r.left = (LONG)aClipRectIn->x;
+ r.top = (LONG)aClipRectIn->y;
+ r.right = (LONG)(aClipRectIn->x + aClipRectIn->width);
+ r.bottom = (LONG)(aClipRectIn->y + aClipRectIn->height);
+ } else {
+ r.left = r.top = 0;
+ r.right = mSize.width;
+ r.bottom = mSize.height;
+ }
+ device()->SetScissorRect(&r);
+
+ RefPtr<IDirect3DSurface9> backBuffer = mSwapChain->GetBackBuffer();
+ mDefaultRT = new CompositingRenderTargetD3D9(backBuffer,
+ INIT_MODE_CLEAR,
+ IntRect(0, 0, mSize.width, mSize.height));
+ SetRenderTarget(mDefaultRT);
+}
+
+void
+CompositorD3D9::EndFrame()
+{
+ if (mDeviceManager) {
+ device()->EndScene();
+
+ LayoutDeviceIntSize oldSize = mSize;
+ EnsureSize();
+ if (oldSize == mSize) {
+ if (mTarget) {
+ PaintToTarget();
+ } else {
+ mSwapChain->Present();
+ }
+ }
+ }
+
+ Compositor::EndFrame();
+
+ mCurrentRT = nullptr;
+ mDefaultRT = nullptr;
+}
+
+void
+CompositorD3D9::PrepareViewport(const gfx::IntSize& aSize)
+{
+ Matrix4x4 viewMatrix;
+ /*
+ * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
+ * <1.0, -1.0> bottomright)
+ */
+ viewMatrix._11 = 2.0f / aSize.width;
+ viewMatrix._22 = -2.0f / aSize.height;
+ viewMatrix._41 = -1.0f;
+ viewMatrix._42 = 1.0f;
+ viewMatrix._33 = 0.0f;
+
+ HRESULT hr = device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
+
+ if (FAILED(hr)) {
+ NS_WARNING("Failed to set projection matrix");
+ }
+}
+
+bool
+CompositorD3D9::SupportsEffect(EffectTypes aEffect)
+{
+ if (aEffect == EffectTypes::COMPONENT_ALPHA &&
+ !mDeviceManager->HasComponentAlpha()) {
+ return false;
+ }
+
+ return Compositor::SupportsEffect(aEffect);
+}
+
+void
+CompositorD3D9::EnsureSize()
+{
+ mSize = mWidget->GetClientSize();
+}
+
+void
+CompositorD3D9::SetSamplerForSamplingFilter(SamplingFilter aSamplingFilter)
+{
+ switch (aSamplingFilter) {
+ case SamplingFilter::LINEAR:
+ device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+ device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ return;
+ case SamplingFilter::POINT:
+ device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ return;
+ default:
+ device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+ device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ }
+}
+
+void
+CompositorD3D9::PaintToTarget()
+{
+ if (!mDeviceManager) {
+ return;
+ }
+
+ RefPtr<IDirect3DSurface9> backBuff;
+ RefPtr<IDirect3DSurface9> destSurf;
+ device()->GetRenderTarget(0, getter_AddRefs(backBuff));
+
+ D3DSURFACE_DESC desc;
+ backBuff->GetDesc(&desc);
+
+ device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
+ D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
+ getter_AddRefs(destSurf), nullptr);
+
+ device()->GetRenderTargetData(backBuff, destSurf);
+
+ D3DLOCKED_RECT rect;
+ HRESULT hr = destSurf->LockRect(&rect, nullptr, D3DLOCK_READONLY);
+ if (FAILED(hr) || !rect.pBits) {
+ gfxCriticalError() << "Failed to lock rect in paint to target D3D9 " << hexa(hr);
+ return;
+ }
+ RefPtr<DataSourceSurface> sourceSurface =
+ Factory::CreateWrappingDataSourceSurface((uint8_t*)rect.pBits,
+ rect.Pitch,
+ IntSize(desc.Width, desc.Height),
+ SurfaceFormat::B8G8R8A8);
+ mTarget->CopySurface(sourceSurface,
+ IntRect(0, 0, desc.Width, desc.Height),
+ IntPoint(-mTargetBounds.x, -mTargetBounds.y));
+ mTarget->Flush();
+ destSurf->UnlockRect();
+}
+
+void
+CompositorD3D9::ReportFailure(const nsACString &aMsg, HRESULT aCode)
+{
+ // We could choose to abort here when hr == E_OUTOFMEMORY.
+ nsCString msg;
+ msg.Append(aMsg);
+ msg.AppendLiteral(" Error code: ");
+ msg.AppendInt(uint32_t(aCode));
+ NS_WARNING(msg.BeginReading());
+
+ gfx::LogFailure(msg);
+}
+
+static inline already_AddRefed<IDirect3DSurface9>
+GetSurfaceOfTexture(IDirect3DTexture9* aTexture)
+{
+ RefPtr<IDirect3DSurface9> surface;
+ HRESULT hr = aTexture->GetSurfaceLevel(0, getter_AddRefs(surface));
+ if (FAILED(hr)) {
+ gfxCriticalNote << "Failed to grab texture surface " << hexa(hr);
+ return nullptr;
+ }
+ return surface.forget();
+}
+
+static inline already_AddRefed<IDirect3DSurface9>
+CreateDataSurfaceForTexture(IDirect3DDevice9* aDevice,
+ IDirect3DSurface9* aSource,
+ const D3DSURFACE_DESC& aDesc)
+{
+ RefPtr<IDirect3DSurface9> dest;
+ HRESULT hr = aDevice->CreateOffscreenPlainSurface(
+ aDesc.Width, aDesc.Height,
+ aDesc.Format, D3DPOOL_SYSTEMMEM,
+ getter_AddRefs(dest), nullptr);
+ if (FAILED(hr) || !dest) {
+ gfxCriticalNote << "Failed to create offscreen plain surface " << hexa(hr);
+ return nullptr;
+ }
+
+ hr = aDevice->GetRenderTargetData(aSource, dest);
+ if (FAILED(hr)) {
+ gfxCriticalNote << "Failed to get render target data " << hexa(hr);
+ return nullptr;
+ }
+
+ return dest.forget();
+}
+
+class AutoSurfaceLock
+{
+ public:
+ AutoSurfaceLock(IDirect3DSurface9* aSurface, DWORD aFlags = 0) {
+ PodZero(&mRect);
+
+ HRESULT hr = aSurface->LockRect(&mRect, nullptr, aFlags);
+ if (FAILED(hr)) {
+ gfxCriticalNote << "Failed to lock surface rect " << hexa(hr);
+ return;
+ }
+ mSurface = aSurface;
+ }
+ ~AutoSurfaceLock() {
+ if (mSurface) {
+ mSurface->UnlockRect();
+ }
+ }
+
+ bool Okay() const {
+ return !!mSurface;
+ }
+ int Pitch() const {
+ MOZ_ASSERT(Okay());
+ return mRect.Pitch;
+ }
+ uint8_t* Bits() const {
+ MOZ_ASSERT(Okay());
+ return reinterpret_cast<uint8_t*>(mRect.pBits);
+ }
+
+ private:
+ RefPtr<IDirect3DSurface9> mSurface;
+ D3DLOCKED_RECT mRect;
+};
+
+void
+CompositorD3D9::FinishMixBlend(const gfx::IntRect& aBackdropRect,
+ const gfx::Rect& aBackdropDest,
+ const gfx::Matrix4x4& aBackdropTransform,
+ RefPtr<IDirect3DTexture9> aBackdrop,
+ gfx::CompositionOp aBlendMode)
+{
+ HRESULT hr;
+
+ RefPtr<IDirect3DTexture9> source =
+ CreateTexture(aBackdropRect, mCurrentRT, aBackdropRect.TopLeft());
+ if (!source) {
+ return;
+ }
+
+ // Slow path - do everything in software. Unfortunately this requires
+ // a lot of copying, since we have to readback the source and backdrop,
+ // then upload the blended result, then blit it back.
+
+ IDirect3DDevice9* d3d9Device = device();
+
+ // Query geometry/format of the two surfaces.
+ D3DSURFACE_DESC backdropDesc, sourceDesc;
+ if (FAILED(aBackdrop->GetLevelDesc(0, &backdropDesc)) ||
+ FAILED(source->GetLevelDesc(0, &sourceDesc)))
+ {
+ gfxCriticalNote << "Failed to query mix-blend texture descriptor";
+ return;
+ }
+
+ MOZ_ASSERT(backdropDesc.Format == D3DFMT_A8R8G8B8);
+ MOZ_ASSERT(sourceDesc.Format == D3DFMT_A8R8G8B8);
+
+ // Acquire a temporary data surface for the backdrop texture.
+ RefPtr<IDirect3DSurface9> backdropSurface = GetSurfaceOfTexture(aBackdrop);
+ if (!backdropSurface) {
+ return;
+ }
+ RefPtr<IDirect3DSurface9> tmpBackdrop =
+ CreateDataSurfaceForTexture(d3d9Device, backdropSurface, backdropDesc);
+ if (!tmpBackdrop) {
+ return;
+ }
+
+ // New scope for locks and temporary surfaces.
+ {
+ // Acquire a temporary data surface for the source texture.
+ RefPtr<IDirect3DSurface9> sourceSurface = GetSurfaceOfTexture(source);
+ if (!sourceSurface) {
+ return;
+ }
+ RefPtr<IDirect3DSurface9> tmpSource =
+ CreateDataSurfaceForTexture(d3d9Device, sourceSurface, sourceDesc);
+ if (!tmpSource) {
+ return;
+ }
+
+ // Perform the readback and blend in software.
+ AutoSurfaceLock backdropLock(tmpBackdrop);
+ AutoSurfaceLock sourceLock(tmpSource, D3DLOCK_READONLY);
+ if (!backdropLock.Okay() || !sourceLock.Okay()) {
+ return;
+ }
+
+ RefPtr<DataSourceSurface> source = Factory::CreateWrappingDataSourceSurface(
+ sourceLock.Bits(), sourceLock.Pitch(),
+ gfx::IntSize(sourceDesc.Width, sourceDesc.Height),
+ SurfaceFormat::B8G8R8A8);
+
+ RefPtr<DrawTarget> dest = Factory::CreateDrawTargetForData(
+ BackendType::CAIRO,
+ backdropLock.Bits(),
+ gfx::IntSize(backdropDesc.Width, backdropDesc.Height),
+ backdropLock.Pitch(),
+ SurfaceFormat::B8G8R8A8);
+
+ // The backdrop rect is rounded out - account for any difference between
+ // it and the actual destination.
+ gfx::Rect destRect(
+ aBackdropDest.x - aBackdropRect.x,
+ aBackdropDest.y - aBackdropRect.y,
+ aBackdropDest.width,
+ aBackdropDest.height);
+
+ dest->DrawSurface(
+ source, destRect, destRect,
+ gfx::DrawSurfaceOptions(),
+ gfx::DrawOptions(1.0f, aBlendMode));
+ }
+
+ // Upload the new blended surface to the backdrop texture.
+ d3d9Device->UpdateSurface(tmpBackdrop, nullptr, backdropSurface, nullptr);
+
+ // Finally, drop in the new backdrop. We don't need to do another
+ // DrawPrimitive() since the software blend will have included the
+ // final OP_OVER step for us.
+ RECT destRect = {
+ aBackdropRect.x, aBackdropRect.y,
+ aBackdropRect.XMost(), aBackdropRect.YMost()
+ };
+ hr = d3d9Device->StretchRect(backdropSurface,
+ nullptr,
+ mCurrentRT->GetD3D9Surface(),
+ &destRect,
+ D3DTEXF_NONE);
+ if (FAILED(hr)) {
+ gfxCriticalNote << "StretcRect with mix-blend failed " << hexa(hr);
+ }
+}
+
+}
+}
diff --git a/gfx/layers/d3d9/CompositorD3D9.h b/gfx/layers/d3d9/CompositorD3D9.h
new file mode 100644
index 000000000..1453d8c7c
--- /dev/null
+++ b/gfx/layers/d3d9/CompositorD3D9.h
@@ -0,0 +1,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
diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.cpp b/gfx/layers/d3d9/DeviceManagerD3D9.cpp
new file mode 100644
index 000000000..09778bc9c
--- /dev/null
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp
@@ -0,0 +1,966 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/. */
+
+#include "DeviceManagerD3D9.h"
+#include "LayerManagerD3D9Shaders.h"
+#include "nsIServiceManager.h"
+#include "nsIConsoleService.h"
+#include "nsPrintfCString.h"
+#include "Nv3DVUtils.h"
+#include "plstr.h"
+#include <algorithm>
+#include "gfx2DGlue.h"
+#include "gfxPlatform.h"
+#include "gfxWindowsPlatform.h"
+#include "TextureD3D9.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/layers/CompositorThread.h"
+#include "gfxPrefs.h"
+
+namespace mozilla {
+namespace layers {
+
+using namespace mozilla::gfx;
+
+const LPCWSTR kClassName = L"D3D9WindowClass";
+
+#define USE_D3D9EX
+
+struct vertex {
+ float x, y;
+};
+
+static StaticAutoPtr<mozilla::Mutex> sDeviceManagerLock;
+static StaticRefPtr<DeviceManagerD3D9> sDeviceManager;
+
+/* static */ void
+DeviceManagerD3D9::Init()
+{
+ MOZ_ASSERT(!sDeviceManagerLock);
+ sDeviceManagerLock = new Mutex("DeviceManagerD3D9.sDeviceManagerLock");
+}
+
+/* static */ void
+DeviceManagerD3D9::Shutdown()
+{
+ sDeviceManagerLock = nullptr;
+ sDeviceManager = nullptr;
+}
+
+SwapChainD3D9::SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager)
+ : mDeviceManager(aDeviceManager)
+ , mWnd(0)
+{
+ mDeviceManager->mSwapChains.AppendElement(this);
+}
+
+SwapChainD3D9::~SwapChainD3D9()
+{
+ mDeviceManager->mSwapChains.RemoveElement(this);
+}
+
+bool
+SwapChainD3D9::Init(HWND hWnd)
+{
+ RECT r;
+ ::GetClientRect(hWnd, &r);
+
+ mWnd = hWnd;
+
+ D3DPRESENT_PARAMETERS pp;
+ memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+ pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+ pp.SwapEffect = D3DSWAPEFFECT_COPY;
+ pp.Windowed = TRUE;
+ pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ pp.hDeviceWindow = mWnd;
+ if (r.left == r.right || r.top == r.bottom) {
+ pp.BackBufferHeight = 1;
+ pp.BackBufferWidth = 1;
+ }
+
+ HRESULT hr = mDeviceManager->device()->
+ CreateAdditionalSwapChain(&pp,
+ getter_AddRefs(mSwapChain));
+
+ if (FAILED(hr)) {
+ NS_WARNING("Failed to create swap chain for window.");
+ return false;
+ }
+
+ return true;
+}
+
+already_AddRefed<IDirect3DSurface9>
+SwapChainD3D9::GetBackBuffer()
+{
+ RefPtr<IDirect3DSurface9> backBuffer;
+ mSwapChain->GetBackBuffer(0,
+ D3DBACKBUFFER_TYPE_MONO,
+ getter_AddRefs(backBuffer));
+ return backBuffer.forget();
+}
+
+DeviceManagerState
+SwapChainD3D9::PrepareForRendering()
+{
+ RECT r;
+ if (!::GetClientRect(mWnd, &r)) {
+ return DeviceFail;
+ }
+
+ DeviceManagerState deviceState = mDeviceManager->VerifyReadyForRendering();
+ if (deviceState != DeviceOK) {
+ return deviceState;
+ }
+
+ if (!mSwapChain) {
+ Init(mWnd);
+ }
+
+ if (mSwapChain) {
+ RefPtr<IDirect3DSurface9> backBuffer = GetBackBuffer();
+
+ D3DSURFACE_DESC desc;
+ backBuffer->GetDesc(&desc);
+
+ if (desc.Width == r.right - r.left && desc.Height == r.bottom - r.top) {
+ mDeviceManager->device()->SetRenderTarget(0, backBuffer);
+ return DeviceOK;
+ }
+
+ mSwapChain = nullptr;
+
+ Init(mWnd);
+
+ if (!mSwapChain) {
+ return DeviceFail;
+ }
+
+ backBuffer = GetBackBuffer();
+ mDeviceManager->device()->SetRenderTarget(0, backBuffer);
+
+ return DeviceOK;
+ }
+
+ return DeviceFail;
+}
+
+void
+SwapChainD3D9::Present(const gfx::IntRect &aRect)
+{
+ RECT r;
+ r.left = aRect.x;
+ r.top = aRect.y;
+ r.right = aRect.XMost();
+ r.bottom = aRect.YMost();
+
+ mSwapChain->Present(&r, &r, 0, 0, 0);
+}
+
+void
+SwapChainD3D9::Present()
+{
+ mSwapChain->Present(nullptr, nullptr, 0, 0, 0);
+}
+
+void
+SwapChainD3D9::Reset()
+{
+ mSwapChain = nullptr;
+}
+
+#define HAS_CAP(a, b) (((a) & (b)) == (b))
+#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
+
+uint32_t DeviceManagerD3D9::sMaskQuadRegister = 11;
+
+DeviceManagerD3D9::DeviceManagerD3D9()
+ : mTextureHostList(nullptr)
+ , mDeviceResetCount(0)
+ , mMaxTextureSize(0)
+ , mTextureAddressingMode(D3DTADDRESS_CLAMP)
+ , mHasComponentAlpha(true)
+ , mHasDynamicTextures(false)
+ , mDeviceWasRemoved(false)
+{
+}
+
+DeviceManagerD3D9::~DeviceManagerD3D9()
+{
+ DestroyDevice();
+}
+
+/* static */ RefPtr<DeviceManagerD3D9>
+DeviceManagerD3D9::Get()
+{
+ MutexAutoLock lock(*sDeviceManagerLock);
+
+ bool canCreate =
+ !gfxPlatform::UsesOffMainThreadCompositing() ||
+ CompositorThreadHolder::IsInCompositorThread();
+ if (!sDeviceManager && canCreate) {
+ sDeviceManager = new DeviceManagerD3D9();
+ if (!sDeviceManager->Initialize()) {
+ gfxCriticalError() << "[D3D9] Could not Initialize the DeviceManagerD3D9";
+ sDeviceManager = nullptr;
+ }
+ }
+
+ return sDeviceManager;
+}
+
+/* static */ RefPtr<IDirect3DDevice9>
+DeviceManagerD3D9::GetDevice()
+{
+ MutexAutoLock lock(*sDeviceManagerLock);
+ return sDeviceManager ? sDeviceManager->device() : nullptr;
+}
+
+/* static */ void
+DeviceManagerD3D9::OnDeviceManagerDestroy(DeviceManagerD3D9* aDeviceManager)
+{
+ if (!sDeviceManagerLock) {
+ // If the device manager has shutdown, we don't care anymore. We can get
+ // here when the compositor shuts down asynchronously.
+ MOZ_ASSERT(!sDeviceManager);
+ return;
+ }
+
+ MutexAutoLock lock(*sDeviceManagerLock);
+ if (aDeviceManager == sDeviceManager) {
+ sDeviceManager = nullptr;
+ }
+}
+
+bool
+DeviceManagerD3D9::Initialize()
+{
+ WNDCLASSW wc;
+ HRESULT hr;
+
+ if (!GetClassInfoW(GetModuleHandle(nullptr), kClassName, &wc)) {
+ ZeroMemory(&wc, sizeof(WNDCLASSW));
+ wc.hInstance = GetModuleHandle(nullptr);
+ wc.lpfnWndProc = ::DefWindowProc;
+ wc.lpszClassName = kClassName;
+ if (!RegisterClassW(&wc)) {
+ gfxCriticalError() << "[D3D9] Failed to register class for DeviceManager";
+ return false;
+ }
+ }
+
+ mFocusWnd = ::CreateWindowW(kClassName, L"D3D9Window", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr,
+ nullptr, GetModuleHandle(nullptr), nullptr);
+
+ if (!mFocusWnd) {
+ gfxCriticalError() << "[D3D9] Failed to create a window";
+ return false;
+ }
+
+ if (gfxPrefs::StereoVideoEnabled()) {
+ /* Create an Nv3DVUtils instance */
+ if (!mNv3DVUtils) {
+ mNv3DVUtils = new Nv3DVUtils();
+ if (!mNv3DVUtils) {
+ NS_WARNING("Could not create a new instance of Nv3DVUtils.");
+ }
+ }
+
+ /* Initialize the Nv3DVUtils object */
+ if (mNv3DVUtils) {
+ mNv3DVUtils->Initialize();
+ }
+ }
+
+ HMODULE d3d9 = LoadLibraryW(L"d3d9.dll");
+ decltype(Direct3DCreate9)* d3d9Create = (decltype(Direct3DCreate9)*)
+ GetProcAddress(d3d9, "Direct3DCreate9");
+ decltype(Direct3DCreate9Ex)* d3d9CreateEx = (decltype(Direct3DCreate9Ex)*)
+ GetProcAddress(d3d9, "Direct3DCreate9Ex");
+
+#ifdef USE_D3D9EX
+ if (d3d9CreateEx) {
+ hr = d3d9CreateEx(D3D_SDK_VERSION, getter_AddRefs(mD3D9Ex));
+ if (SUCCEEDED(hr)) {
+ mD3D9 = mD3D9Ex;
+ }
+ }
+#endif
+
+ if (!mD3D9) {
+ if (!d3d9Create) {
+ gfxCriticalError() << "[D3D9] Failed to load symbols";
+ return false;
+ }
+
+ mD3D9 = dont_AddRef(d3d9Create(D3D_SDK_VERSION));
+
+ if (!mD3D9) {
+ gfxCriticalError() << "[D3D9] Failed to create the IDirect3D9 object";
+ return false;
+ }
+ }
+
+ D3DADAPTER_IDENTIFIER9 ident;
+ hr = mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &ident);
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << "[D3D9] Failed to create the environment code: " << gfx::hexa(hr);
+ return false;
+ }
+
+ D3DPRESENT_PARAMETERS pp;
+ memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+ pp.BackBufferWidth = 1;
+ pp.BackBufferHeight = 1;
+ pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+ pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ pp.Windowed = TRUE;
+ pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ pp.hDeviceWindow = mFocusWnd;
+
+ if (mD3D9Ex) {
+ hr = mD3D9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL,
+ mFocusWnd,
+ D3DCREATE_FPU_PRESERVE |
+ D3DCREATE_MULTITHREADED |
+ D3DCREATE_MIXED_VERTEXPROCESSING,
+ &pp,
+ nullptr,
+ getter_AddRefs(mDeviceEx));
+ if (SUCCEEDED(hr)) {
+ mDevice = mDeviceEx;
+ }
+
+ D3DCAPS9 caps;
+ if (mDeviceEx && mDeviceEx->GetDeviceCaps(&caps)) {
+ if (LACKS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
+ // XXX - Should we actually hit this we'll need a CanvasLayer that
+ // supports static D3DPOOL_DEFAULT textures.
+ NS_WARNING("D3D9Ex device not used because of lack of support for \
+ dynamic textures. This is unexpected.");
+ mDevice = nullptr;
+ mDeviceEx = nullptr;
+ }
+ }
+ }
+
+ if (!mDevice) {
+ hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL,
+ mFocusWnd,
+ D3DCREATE_FPU_PRESERVE |
+ D3DCREATE_MULTITHREADED |
+ D3DCREATE_MIXED_VERTEXPROCESSING,
+ &pp,
+ getter_AddRefs(mDevice));
+
+ if (FAILED(hr) || !mDevice) {
+ gfxCriticalError() << "[D3D9] Failed to create the device, code: " << hexa(hr);
+ return false;
+ }
+ }
+
+ if (!VerifyCaps()) {
+ gfxCriticalError() << "[D3D9] insufficient capabilities";
+ return false;
+ }
+
+ /* Grab the associated HMONITOR so that we can find out
+ * if it changed later */
+ D3DDEVICE_CREATION_PARAMETERS parameters;
+ if (FAILED(mDevice->GetCreationParameters(&parameters)))
+ return false;
+ mDeviceMonitor = mD3D9->GetAdapterMonitor(parameters.AdapterOrdinal);
+
+
+ /*
+ * Do some post device creation setup
+ */
+ if (mNv3DVUtils) {
+ IUnknown* devUnknown = nullptr;
+ if (mDevice) {
+ mDevice->QueryInterface(IID_IUnknown, (void **)&devUnknown);
+ }
+ mNv3DVUtils->SetDeviceInfo(devUnknown);
+ }
+
+ auto failCreateShaderMsg = "[D3D9] failed to create a critical resource (shader) code";
+
+ hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
+ getter_AddRefs(mLayerVS));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "LayerQuadVS: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
+ getter_AddRefs(mRGBPS));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "RGBShaderPS: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPS,
+ getter_AddRefs(mRGBAPS));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "RGBAShaderPS: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPS,
+ getter_AddRefs(mComponentPass1PS));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "ComponentPass1ShaderPS: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)ComponentPass2ShaderPS,
+ getter_AddRefs(mComponentPass2PS));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "ComponentPass2ShaderPS: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
+ getter_AddRefs(mYCbCrPS));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "YCbCrShaderPS: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
+ getter_AddRefs(mSolidColorPS));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "SolidColorShaderPS" << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask,
+ getter_AddRefs(mLayerVSMask));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "LayerQuadVSMask: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPSMask,
+ getter_AddRefs(mRGBPSMask));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "RGBShaderPSMask " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask,
+ getter_AddRefs(mRGBAPSMask));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "RGBAShaderPSMask: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPSMask,
+ getter_AddRefs(mComponentPass1PSMask));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "ComponentPass1ShaderPSMask: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)ComponentPass2ShaderPSMask,
+ getter_AddRefs(mComponentPass2PSMask));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "ComponentPass2ShaderPSMask: ";
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPSMask,
+ getter_AddRefs(mYCbCrPSMask));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "YCbCrShaderPSMask: " << gfx::hexa(hr);
+ return false;
+ }
+
+ hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPSMask,
+ getter_AddRefs(mSolidColorPSMask));
+
+ if (FAILED(hr)) {
+ gfxCriticalError() << failCreateShaderMsg << "SolidColorShaderPSMask: " << gfx::hexa(hr);
+ return false;
+ }
+
+ if (!CreateVertexBuffer()) {
+ gfxCriticalError() << "[D3D9] Failed to create a critical resource (vbo)";
+ return false;
+ }
+
+ hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
+ if (FAILED(hr)) {
+ gfxCriticalError() << "[D3D9] Failed to set the stream source code: " << gfx::hexa(hr);
+ return false;
+ }
+
+ D3DVERTEXELEMENT9 elements[] = {
+ { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
+ D3DDECLUSAGE_POSITION, 0 },
+ D3DDECL_END()
+ };
+
+ mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
+
+ nsCOMPtr<nsIConsoleService>
+ console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+
+ D3DADAPTER_IDENTIFIER9 identifier;
+ mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
+
+ if (console) {
+ nsString msg;
+ msg +=
+ NS_LITERAL_STRING("Direct3D 9 DeviceManager Initialized Successfully.\nDriver: ");
+ msg += NS_ConvertUTF8toUTF16(
+ nsDependentCString((const char*)identifier.Driver));
+ msg += NS_LITERAL_STRING("\nDescription: ");
+ msg += NS_ConvertUTF8toUTF16(
+ nsDependentCString((const char*)identifier.Description));
+ msg += NS_LITERAL_STRING("\nVersion: ");
+ msg += NS_ConvertUTF8toUTF16(
+ nsPrintfCString("%d.%d.%d.%d",
+ HIWORD(identifier.DriverVersion.HighPart),
+ LOWORD(identifier.DriverVersion.HighPart),
+ HIWORD(identifier.DriverVersion.LowPart),
+ LOWORD(identifier.DriverVersion.LowPart)));
+ console->LogStringMessage(msg.get());
+ }
+
+ return true;
+}
+
+void
+DeviceManagerD3D9::SetupRenderState()
+{
+ mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
+ mDevice->SetVertexDeclaration(mVD);
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+ mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+ mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+ mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
+ mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
+ mDevice->SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD);
+ mDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+ mDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ mDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+ mDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ mDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+ mDevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, mTextureAddressingMode);
+ mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, mTextureAddressingMode);
+ mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, mTextureAddressingMode);
+ mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, mTextureAddressingMode);
+ mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, mTextureAddressingMode);
+ mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, mTextureAddressingMode);
+}
+
+already_AddRefed<SwapChainD3D9>
+DeviceManagerD3D9::CreateSwapChain(HWND hWnd)
+{
+ RefPtr<SwapChainD3D9> swapChain = new SwapChainD3D9(this);
+
+ // See bug 604647. This line means that if we create a window while the
+ // device is lost LayerManager initialization will fail, this window
+ // will be permanently unaccelerated. This should be a rare situation
+ // though and the need for a low-risk fix for this bug outweighs the
+ // downside.
+ if (VerifyReadyForRendering() != DeviceOK) {
+ return nullptr;
+ }
+
+ if (!swapChain->Init(hWnd)) {
+ return nullptr;
+ }
+
+ return swapChain.forget();
+}
+
+uint32_t
+DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, MaskType aMaskType)
+{
+ if (aMaskType == MaskType::MaskNone) {
+ switch (aMode) {
+ case RGBLAYER:
+ mDevice->SetVertexShader(mLayerVS);
+ mDevice->SetPixelShader(mRGBPS);
+ break;
+ case RGBALAYER:
+ mDevice->SetVertexShader(mLayerVS);
+ mDevice->SetPixelShader(mRGBAPS);
+ break;
+ case COMPONENTLAYERPASS1:
+ mDevice->SetVertexShader(mLayerVS);
+ mDevice->SetPixelShader(mComponentPass1PS);
+ break;
+ case COMPONENTLAYERPASS2:
+ mDevice->SetVertexShader(mLayerVS);
+ mDevice->SetPixelShader(mComponentPass2PS);
+ break;
+ case YCBCRLAYER:
+ mDevice->SetVertexShader(mLayerVS);
+ mDevice->SetPixelShader(mYCbCrPS);
+ break;
+ case SOLIDCOLORLAYER:
+ mDevice->SetVertexShader(mLayerVS);
+ mDevice->SetPixelShader(mSolidColorPS);
+ break;
+ }
+ return 0;
+ }
+
+ uint32_t maskTexRegister;
+ switch (aMode) {
+ case RGBLAYER:
+ mDevice->SetVertexShader(mLayerVSMask);
+ mDevice->SetPixelShader(mRGBPSMask);
+ maskTexRegister = 1;
+ break;
+ case RGBALAYER:
+ mDevice->SetVertexShader(mLayerVSMask);
+ mDevice->SetPixelShader(mRGBAPSMask);
+ maskTexRegister = 1;
+ break;
+ case COMPONENTLAYERPASS1:
+ mDevice->SetVertexShader(mLayerVSMask);
+ mDevice->SetPixelShader(mComponentPass1PSMask);
+ maskTexRegister = 2;
+ break;
+ case COMPONENTLAYERPASS2:
+ mDevice->SetVertexShader(mLayerVSMask);
+ mDevice->SetPixelShader(mComponentPass2PSMask);
+ maskTexRegister = 2;
+ break;
+ case YCBCRLAYER:
+ mDevice->SetVertexShader(mLayerVSMask);
+ mDevice->SetPixelShader(mYCbCrPSMask);
+ maskTexRegister = 3;
+ break;
+ case SOLIDCOLORLAYER:
+ mDevice->SetVertexShader(mLayerVSMask);
+ mDevice->SetPixelShader(mSolidColorPSMask);
+ maskTexRegister = 0;
+ break;
+ }
+ return maskTexRegister;
+}
+
+void
+DeviceManagerD3D9::DestroyDevice()
+{
+ ++mDeviceResetCount;
+ mDeviceWasRemoved = true;
+ if (!IsD3D9Ex()) {
+ ReleaseTextureResources();
+ }
+ DeviceManagerD3D9::OnDeviceManagerDestroy(this);
+}
+
+DeviceManagerState
+DeviceManagerD3D9::VerifyReadyForRendering()
+{
+ if (mDeviceWasRemoved) {
+ return DeviceMustRecreate;
+ }
+
+ HRESULT hr = mDevice->TestCooperativeLevel();
+
+ if (SUCCEEDED(hr)) {
+ if (IsD3D9Ex()) {
+ hr = mDeviceEx->CheckDeviceState(mFocusWnd);
+
+ if (FAILED(hr)) {
+ DestroyDevice();
+ return DeviceMustRecreate;
+ }
+ }
+ return DeviceOK;
+ }
+
+ ReleaseTextureResources();
+ for (unsigned int i = 0; i < mSwapChains.Length(); i++) {
+ mSwapChains[i]->Reset();
+ }
+
+ mVB = nullptr;
+
+ D3DPRESENT_PARAMETERS pp;
+ memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+ pp.BackBufferWidth = 1;
+ pp.BackBufferHeight = 1;
+ pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+ pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ pp.Windowed = TRUE;
+ pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ pp.hDeviceWindow = mFocusWnd;
+
+ // Whatever happens from now on, either we reset the device, or we should
+ // pretend we reset the device so that the layer manager or compositor
+ // doesn't ignore it.
+ ++mDeviceResetCount;
+
+ // if we got this far, we know !SUCCEEDEED(hr), that means hr is one of
+ // D3DERR_DEVICELOST, D3DERR_DEVICENOTRESET, D3DERR_DRIVERINTERNALERROR.
+ // It is only worth resetting if we get D3DERR_DEVICENOTRESET. If we get
+ // D3DERR_DEVICELOST we can wait and see if we get D3DERR_DEVICENOTRESET
+ // later, then reset.
+ if (hr == D3DERR_DEVICELOST) {
+ HMONITOR hMonitorWindow;
+ hMonitorWindow = MonitorFromWindow(mFocusWnd, MONITOR_DEFAULTTOPRIMARY);
+ if (hMonitorWindow != mDeviceMonitor) {
+ /* jrmuizel: I'm not sure how to trigger this case. Usually, we get
+ * DEVICENOTRESET right away and Reset() succeeds without going through a
+ * set of DEVICELOSTs. This is presumeably because we don't call
+ * VerifyReadyForRendering when we don't have any reason to paint.
+ * Hopefully comparing HMONITORs is not overly aggressive.
+ * See bug 626678.
+ */
+ /* The monitor has changed. We have to assume that the
+ * DEVICENOTRESET will not be coming. */
+ DestroyDevice();
+ return DeviceMustRecreate;
+ }
+ return DeviceFail;
+ }
+ if (hr == D3DERR_DEVICENOTRESET) {
+ hr = mDevice->Reset(&pp);
+ }
+
+ if (FAILED(hr) || !CreateVertexBuffer()) {
+ DestroyDevice();
+ return DeviceMustRecreate;
+ }
+
+ return DeviceOK;
+}
+
+bool
+DeviceManagerD3D9::VerifyCaps()
+{
+ D3DCAPS9 caps;
+ HRESULT hr = mDevice->GetDeviceCaps(&caps);
+
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
+ return false;
+ }
+
+ if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
+ return false;
+ }
+
+ if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
+ LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
+ LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
+ return false;
+ }
+
+ if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
+ return false;
+ }
+
+ if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
+ HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
+ (HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
+ LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
+ return false;
+ }
+
+ if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
+ LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
+ return false;
+ }
+
+ if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
+ return false;
+ }
+
+ if (caps.MaxTextureHeight < 4096 ||
+ caps.MaxTextureWidth < 4096) {
+ return false;
+ }
+ mMaxTextureSize = std::min(caps.MaxTextureHeight, caps.MaxTextureWidth);
+
+ if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
+ (caps.VertexShaderVersion & 0xffff) < 0x200) {
+ return false;
+ }
+
+ if (HAS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
+ mHasDynamicTextures = true;
+ }
+
+ if (HAS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_WRAP) &&
+ LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) {
+ mTextureAddressingMode = D3DTADDRESS_WRAP;
+ } else {
+ gfxPlatform::DisableBufferRotation();
+ }
+
+ if (LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCCOLOR)) {
+ mHasComponentAlpha = false;
+ }
+
+ return true;
+}
+
+bool
+DeviceManagerD3D9::CreateVertexBuffer()
+{
+ HRESULT hr;
+
+ hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
+ D3DUSAGE_WRITEONLY,
+ 0,
+ D3DPOOL_DEFAULT,
+ getter_AddRefs(mVB),
+ nullptr);
+
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ vertex *vertices;
+ hr = mVB->Lock(0, 0, (void**)&vertices, 0);
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ vertices[0].x = vertices[0].y = 0;
+ vertices[1].x = 1; vertices[1].y = 0;
+ vertices[2].x = 0; vertices[2].y = 1;
+ vertices[3].x = 1; vertices[3].y = 1;
+
+ mVB->Unlock();
+
+ return true;
+}
+
+already_AddRefed<IDirect3DTexture9>
+DeviceManagerD3D9::CreateTexture(const IntSize &aSize,
+ _D3DFORMAT aFormat,
+ D3DPOOL aPool,
+ TextureSourceD3D9* aTextureHost)
+{
+ if (mDeviceWasRemoved) {
+ return nullptr;
+ }
+ RefPtr<IDirect3DTexture9> result;
+ if (FAILED(device()->CreateTexture(aSize.width, aSize.height,
+ 1, 0, aFormat, aPool,
+ getter_AddRefs(result), nullptr))) {
+ return nullptr;
+ }
+
+ NS_ASSERTION(aPool != D3DPOOL_MANAGED,
+ "Should not be using MANAGED texture pool. We will get an error when we have to recreate the device");
+ if (aPool == D3DPOOL_DEFAULT) {
+ MOZ_ASSERT(aTextureHost, "We need a texture host to track so we can release the texture.");
+ RegisterTextureHost(aTextureHost);
+ }
+
+ return result.forget();
+}
+
+#ifdef DEBUG
+bool
+DeviceManagerD3D9::IsInTextureHostList(TextureSourceD3D9* aFind)
+{
+ TextureSourceD3D9* cur = mTextureHostList;
+ while(cur) {
+ if (cur == aFind) {
+ return true;
+ }
+ cur = cur->mNextHost;
+ }
+
+ return false;
+}
+#endif
+
+void
+DeviceManagerD3D9::RegisterTextureHost(TextureSourceD3D9* aHost)
+{
+ if (!aHost) {
+ return;
+ }
+
+ // Don't add aHost to the list twice.
+ if (aHost->mPreviousHost ||
+ mTextureHostList == aHost) {
+ MOZ_ASSERT(IsInTextureHostList(aHost));
+ return;
+ }
+
+ MOZ_ASSERT(!aHost->mNextHost);
+ MOZ_ASSERT(!IsInTextureHostList(aHost));
+
+ if (mTextureHostList) {
+ MOZ_ASSERT(!mTextureHostList->mPreviousHost);
+ mTextureHostList->mPreviousHost = aHost;
+ aHost->mNextHost = mTextureHostList;
+ }
+ mTextureHostList = aHost;
+ MOZ_ASSERT(!aHost->mCreatingDeviceManager, "Already created texture?");
+ MOZ_ASSERT(IsInTextureHostList(aHost));
+ aHost->mCreatingDeviceManager = this;
+}
+
+void
+DeviceManagerD3D9::ReleaseTextureResources()
+{
+ TextureSourceD3D9* host = mTextureHostList;
+ while (host) {
+ host->ReleaseTextureResources();
+ TextureSourceD3D9* oldHost = host;
+ host = oldHost->mNextHost;
+ oldHost->mPreviousHost = nullptr;
+ oldHost->mNextHost = nullptr;
+ oldHost->mCreatingDeviceManager = nullptr;
+ }
+ mTextureHostList = nullptr;
+}
+
+void
+DeviceManagerD3D9::RemoveTextureListHead(TextureSourceD3D9* aHost)
+{
+ MOZ_ASSERT(!aHost->mCreatingDeviceManager || aHost->mCreatingDeviceManager == this,
+ "Wrong device manager");
+ MOZ_ASSERT(aHost && mTextureHostList == aHost,
+ "aHost is not the head of the texture host list");
+ mTextureHostList = aHost->mNextHost;
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.h b/gfx/layers/d3d9/DeviceManagerD3D9.h
new file mode 100644
index 000000000..d27b679ab
--- /dev/null
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.h
@@ -0,0 +1,353 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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 GFX_DEVICEMANAGERD3D9_H
+#define GFX_DEVICEMANAGERD3D9_H
+
+#include "gfxTypes.h"
+#include "nsAutoPtr.h"
+#include "d3d9.h"
+#include "nsTArray.h"
+#include "mozilla/layers/CompositorTypes.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/gfx/Rect.h"
+
+namespace mozilla {
+namespace layers {
+
+class DeviceManagerD3D9;
+class Nv3DVUtils;
+class Layer;
+class TextureSourceD3D9;
+
+// Shader Constant locations
+const int CBmLayerTransform = 0;
+const int CBmProjection = 4;
+const int CBvRenderTargetOffset = 8;
+const int CBvTextureCoords = 9;
+const int CBvLayerQuad = 10;
+// we don't use opacity with solid color shaders
+const int CBfLayerOpacity = 0;
+const int CBvColor = 0;
+const int CBmYuvColorMatrix = 1;
+
+enum DeviceManagerState {
+ // The device and swap chain are OK.
+ DeviceOK,
+ // The device or swap chain are in a bad state, and we should not render.
+ DeviceFail,
+ // The device is lost and cannot be reset, the user should forget the
+ // current device manager and create a new one.
+ DeviceMustRecreate,
+};
+
+
+/**
+ * This structure is used to pass rectangles to our shader constant. We can use
+ * this for passing rectangular areas to SetVertexShaderConstant. In the format
+ * of a 4 component float(x,y,width,height). Our vertex shader can then use
+ * this to construct rectangular positions from the 0,0-1,1 quad that we source
+ * it with.
+ */
+struct ShaderConstantRect
+{
+ float mX, mY, mWidth, mHeight;
+
+ // Provide all the commonly used argument types to prevent all the local
+ // casts in the code.
+ ShaderConstantRect(float aX, float aY, float aWidth, float aHeight)
+ : mX(aX), mY(aY), mWidth(aWidth), mHeight(aHeight)
+ { }
+
+ ShaderConstantRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight)
+ : mX((float)aX), mY((float)aY)
+ , mWidth((float)aWidth), mHeight((float)aHeight)
+ { }
+
+ ShaderConstantRect(int32_t aX, int32_t aY, float aWidth, float aHeight)
+ : mX((float)aX), mY((float)aY), mWidth(aWidth), mHeight(aHeight)
+ { }
+
+ // For easy passing to SetVertexShaderConstantF.
+ operator float* () { return &mX; }
+};
+
+/**
+ * SwapChain class, this class manages the swap chain belonging to a
+ * LayerManagerD3D9.
+ */
+class SwapChainD3D9 final
+{
+ NS_INLINE_DECL_REFCOUNTING(SwapChainD3D9)
+public:
+
+ /**
+ * This function will prepare the device this swap chain belongs to for
+ * rendering to this swap chain. Only after calling this function can the
+ * swap chain be drawn to, and only until this function is called on another
+ * swap chain belonging to this device will the device draw to it. Passed in
+ * is the size of the swap chain. If the window size differs from the size
+ * during the last call to this function the swap chain will resize. Note that
+ * in no case does this function guarantee the backbuffer to still have its
+ * old content.
+ */
+ DeviceManagerState PrepareForRendering();
+
+ already_AddRefed<IDirect3DSurface9> GetBackBuffer();
+
+ /**
+ * This function will present the selected rectangle of the swap chain to
+ * its associated window.
+ */
+ void Present(const gfx::IntRect &aRect);
+ void Present();
+
+private:
+ friend class DeviceManagerD3D9;
+
+ SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager);
+
+ // Private destructor, to discourage deletion outside of Release():
+ ~SwapChainD3D9();
+
+ bool Init(HWND hWnd);
+
+ /**
+ * This causes us to release our swap chain, clearing out our resource usage
+ * so the master device may reset.
+ */
+ void Reset();
+
+ RefPtr<IDirect3DSwapChain9> mSwapChain;
+ RefPtr<DeviceManagerD3D9> mDeviceManager;
+ HWND mWnd;
+};
+
+/**
+ * Device manager, this class is used by the layer managers to share the D3D9
+ * device and create swap chains for the individual windows the layer managers
+ * belong to.
+ */
+class DeviceManagerD3D9 final
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceManagerD3D9)
+
+ /**
+ * Setup or tear down static resources needed for D3D9.
+ */
+ static void Init();
+ static void Shutdown();
+
+ /**
+ * Static accessors and helpers for accessing the global DeviceManagerD3D9
+ * instance.
+ */
+ static RefPtr<DeviceManagerD3D9> Get();
+ static RefPtr<IDirect3DDevice9> GetDevice();
+ static void OnDeviceManagerDestroy(DeviceManagerD3D9* aDeviceManager);
+
+ /**
+ * Sets up the render state for the device for layer rendering.
+ */
+ void SetupRenderState();
+
+ /**
+ * Create a swap chain setup to work with the specified window.
+ */
+ already_AddRefed<SwapChainD3D9> CreateSwapChain(HWND hWnd);
+
+ IDirect3DDevice9 *device() { return mDevice; }
+
+ bool IsD3D9Ex() { return mDeviceEx; }
+
+ bool HasComponentAlpha() { return mHasComponentAlpha; }
+
+ bool HasDynamicTextures() { return mHasDynamicTextures; }
+
+ enum ShaderMode {
+ RGBLAYER,
+ RGBALAYER,
+ COMPONENTLAYERPASS1,
+ COMPONENTLAYERPASS2,
+ YCBCRLAYER,
+ SOLIDCOLORLAYER
+ };
+
+ // returns the register to be used for the mask texture, if appropriate
+ uint32_t SetShaderMode(ShaderMode aMode, MaskType aMaskType);
+
+ /**
+ * Return pointer to the Nv3DVUtils instance
+ */
+ Nv3DVUtils *GetNv3DVUtils() { return mNv3DVUtils; }
+
+ /**
+ * Returns true if this device was removed.
+ */
+ bool DeviceWasRemoved() { return mDeviceWasRemoved; }
+
+ uint32_t GetDeviceResetCount() { return mDeviceResetCount; }
+
+ int32_t GetMaxTextureSize() { return mMaxTextureSize; }
+
+ // Removes aHost from our list of texture hosts if it is the head.
+ void RemoveTextureListHead(TextureSourceD3D9* aHost);
+
+ /**
+ * Creates a texture using our device.
+ * If needed, we keep a record of the new texture, so the texture can be
+ * released. In this case, aTextureHostIDirect3DTexture9 must be non-null.
+ */
+ already_AddRefed<IDirect3DTexture9> CreateTexture(const gfx::IntSize &aSize,
+ _D3DFORMAT aFormat,
+ D3DPOOL aPool,
+ TextureSourceD3D9* aTextureHostIDirect3DTexture9);
+#ifdef DEBUG
+ // Looks for aFind in the list of texture hosts.
+ // O(n) so only use for assertions.
+ bool IsInTextureHostList(TextureSourceD3D9* aFind);
+#endif
+
+ /**
+ * This function verifies the device is ready for rendering, internally this
+ * will test the cooperative level of the device and reset the device if
+ * needed. If this returns false subsequent rendering calls may return errors.
+ */
+ DeviceManagerState VerifyReadyForRendering();
+
+ static uint32_t sMaskQuadRegister;
+
+private:
+ friend class SwapChainD3D9;
+
+ DeviceManagerD3D9();
+ ~DeviceManagerD3D9();
+
+ /**
+ * Initialises the device manager, the underlying device, and everything else
+ * the manager needs.
+ * Returns true if initialisation succeeds, false otherwise.
+ * Note that if initisalisation fails, you cannot try again - you must throw
+ * away the DeviceManagerD3D9 and create a new one.
+ */
+ bool Initialize();
+
+ void DestroyDevice();
+
+ /**
+ * This will fill our vertex buffer with the data of our quad, it may be
+ * called when the vertex buffer is recreated.
+ */
+ bool CreateVertexBuffer();
+
+ /**
+ * Release all textures created by this device manager.
+ */
+ void ReleaseTextureResources();
+ /**
+ * Add aHost to our list of texture hosts.
+ */
+ void RegisterTextureHost(TextureSourceD3D9* aHost);
+
+ /* Array used to store all swap chains for device resets */
+ nsTArray<SwapChainD3D9*> mSwapChains;
+
+ /* The D3D device we use */
+ RefPtr<IDirect3DDevice9> mDevice;
+
+ /* The D3D9Ex device - only valid on Vista+ with WDDM */
+ RefPtr<IDirect3DDevice9Ex> mDeviceEx;
+
+ /* An instance of the D3D9 object */
+ RefPtr<IDirect3D9> mD3D9;
+
+ /* An instance of the D3D9Ex object - only valid on Vista+ with WDDM */
+ RefPtr<IDirect3D9Ex> mD3D9Ex;
+
+ /* Vertex shader used for layer quads */
+ RefPtr<IDirect3DVertexShader9> mLayerVS;
+
+ /* Pixel shader used for RGB textures */
+ RefPtr<IDirect3DPixelShader9> mRGBPS;
+
+ /* Pixel shader used for RGBA textures */
+ RefPtr<IDirect3DPixelShader9> mRGBAPS;
+
+ /* Pixel shader used for component alpha textures (pass 1) */
+ RefPtr<IDirect3DPixelShader9> mComponentPass1PS;
+
+ /* Pixel shader used for component alpha textures (pass 2) */
+ RefPtr<IDirect3DPixelShader9> mComponentPass2PS;
+
+ /* Pixel shader used for RGB textures */
+ RefPtr<IDirect3DPixelShader9> mYCbCrPS;
+
+ /* Pixel shader used for solid colors */
+ RefPtr<IDirect3DPixelShader9> mSolidColorPS;
+
+ /* As above, but using a mask layer */
+ RefPtr<IDirect3DVertexShader9> mLayerVSMask;
+ RefPtr<IDirect3DPixelShader9> mRGBPSMask;
+ RefPtr<IDirect3DPixelShader9> mRGBAPSMask;
+ RefPtr<IDirect3DPixelShader9> mComponentPass1PSMask;
+ RefPtr<IDirect3DPixelShader9> mComponentPass2PSMask;
+ RefPtr<IDirect3DPixelShader9> mYCbCrPSMask;
+ RefPtr<IDirect3DPixelShader9> mSolidColorPSMask;
+
+ /* Vertex buffer containing our basic vertex structure */
+ RefPtr<IDirect3DVertexBuffer9> mVB;
+
+ /* Our vertex declaration */
+ RefPtr<IDirect3DVertexDeclaration9> mVD;
+
+ /* We maintain a doubly linked list of all d3d9 texture hosts which host
+ * d3d9 textures created by this device manager.
+ * Texture hosts must remove themselves when they disappear (i.e., we
+ * expect all hosts in the list to be valid).
+ * The list is cleared when we release the textures.
+ */
+ TextureSourceD3D9* mTextureHostList;
+
+ /* Our focus window - this is really a dummy window we can associate our
+ * device with.
+ */
+ HWND mFocusWnd;
+
+ /* we use this to help track if our device temporarily or permanently lost */
+ HMONITOR mDeviceMonitor;
+
+ uint32_t mDeviceResetCount;
+
+ uint32_t mMaxTextureSize;
+
+ /**
+ * Wrap (repeat) or clamp textures. We prefer the former so we can do buffer
+ * rotation, but some older hardware doesn't support it.
+ */
+ D3DTEXTUREADDRESS mTextureAddressingMode;
+
+ /* If this device supports component alpha */
+ bool mHasComponentAlpha;
+
+ /* If this device supports dynamic textures */
+ bool mHasDynamicTextures;
+
+ /* If this device was removed */
+ bool mDeviceWasRemoved;
+
+ /* Nv3DVUtils instance */
+ nsAutoPtr<Nv3DVUtils> mNv3DVUtils;
+
+ /**
+ * Verifies all required device capabilities are present.
+ */
+ bool VerifyCaps();
+};
+
+} /* namespace layers */
+} /* namespace mozilla */
+
+#endif /* GFX_DEVICEMANAGERD3D9_H */
diff --git a/gfx/layers/d3d9/LayerManagerD3D9Shaders.h b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h
new file mode 100755
index 000000000..105970c0a
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h
@@ -0,0 +1,1631 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float4x4 mLayerTransform;
+// float4x4 mProjection;
+// float4 vLayerQuad;
+// float4 vRenderTargetOffset;
+// float4 vTextureCoords;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------------- ----- ----
+// mLayerTransform c0 4
+// mProjection c4 4
+// vRenderTargetOffset c8 1
+// vTextureCoords c9 1
+// vLayerQuad c10 1
+//
+
+ vs_2_0
+ def c11, -0.5, 0, 0, 0
+ dcl_position v0
+ mad r0.xy, v0, c10.zwzw, c10
+ mul r1, r0.y, c1
+ mad r0, c0, r0.x, r1
+ mad r0, c2, v0.z, r0
+ mad r0, c3, v0.w, r0
+ rcp r1.x, r0.w
+ mul r0.xyz, r0, r1.x
+ add r0, r0, -c8
+ mad r0.xy, r0, r0.w, c11.x
+ mul r1, r0.y, c5
+ mad r1, c4, r0.x, r1
+ mul r0.x, r0.w, r0.z
+ mad r1, c6, r0.x, r1
+ mad oPos, c7, r0.w, r1
+ mad oT0.xy, v0, c9.zwzw, c9
+
+// approximately 15 instruction slots used
+#endif
+
+const BYTE LayerQuadVS[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 76, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 2, 1,
+ 0, 0, 0, 2, 254, 255,
+ 5, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 251, 0, 0, 0, 128, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 144, 0,
+ 0, 0, 0, 0, 0, 0,
+ 160, 0, 0, 0, 2, 0,
+ 4, 0, 4, 0, 0, 0,
+ 144, 0, 0, 0, 0, 0,
+ 0, 0, 172, 0, 0, 0,
+ 2, 0, 10, 0, 1, 0,
+ 0, 0, 184, 0, 0, 0,
+ 0, 0, 0, 0, 200, 0,
+ 0, 0, 2, 0, 8, 0,
+ 1, 0, 0, 0, 220, 0,
+ 0, 0, 0, 0, 0, 0,
+ 236, 0, 0, 0, 2, 0,
+ 9, 0, 1, 0, 0, 0,
+ 184, 0, 0, 0, 0, 0,
+ 0, 0, 109, 76, 97, 121,
+ 101, 114, 84, 114, 97, 110,
+ 115, 102, 111, 114, 109, 0,
+ 3, 0, 3, 0, 4, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 109, 80,
+ 114, 111, 106, 101, 99, 116,
+ 105, 111, 110, 0, 118, 76,
+ 97, 121, 101, 114, 81, 117,
+ 97, 100, 0, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 118, 82, 101, 110,
+ 100, 101, 114, 84, 97, 114,
+ 103, 101, 116, 79, 102, 102,
+ 115, 101, 116, 0, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 118, 84, 101, 120,
+ 116, 117, 114, 101, 67, 111,
+ 111, 114, 100, 115, 0, 118,
+ 115, 95, 50, 95, 48, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 49,
+ 48, 46, 49, 0, 171, 171,
+ 81, 0, 0, 5, 11, 0,
+ 15, 160, 0, 0, 0, 191,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 15, 144,
+ 4, 0, 0, 4, 0, 0,
+ 3, 128, 0, 0, 228, 144,
+ 10, 0, 238, 160, 10, 0,
+ 228, 160, 5, 0, 0, 3,
+ 1, 0, 15, 128, 0, 0,
+ 85, 128, 1, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 128, 0, 0, 228, 160,
+ 0, 0, 0, 128, 1, 0,
+ 228, 128, 4, 0, 0, 4,
+ 0, 0, 15, 128, 2, 0,
+ 228, 160, 0, 0, 170, 144,
+ 0, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 128,
+ 3, 0, 228, 160, 0, 0,
+ 255, 144, 0, 0, 228, 128,
+ 6, 0, 0, 2, 1, 0,
+ 1, 128, 0, 0, 255, 128,
+ 5, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 228, 128,
+ 1, 0, 0, 128, 2, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 8, 0,
+ 228, 161, 4, 0, 0, 4,
+ 0, 0, 3, 128, 0, 0,
+ 228, 128, 0, 0, 255, 128,
+ 11, 0, 0, 160, 5, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 85, 128, 5, 0,
+ 228, 160, 4, 0, 0, 4,
+ 1, 0, 15, 128, 4, 0,
+ 228, 160, 0, 0, 0, 128,
+ 1, 0, 228, 128, 5, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 255, 128, 0, 0,
+ 170, 128, 4, 0, 0, 4,
+ 1, 0, 15, 128, 6, 0,
+ 228, 160, 0, 0, 0, 128,
+ 1, 0, 228, 128, 4, 0,
+ 0, 4, 0, 0, 15, 192,
+ 7, 0, 228, 160, 0, 0,
+ 255, 128, 1, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 3, 224, 0, 0, 228, 144,
+ 9, 0, 238, 160, 9, 0,
+ 228, 160, 255, 255, 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// sampler2D s2D;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// fLayerOpacity c0 1
+// s2D s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mul r0, r0, c0.x
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+#endif
+
+const BYTE RGBAShaderPS[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 43, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 127, 0,
+ 0, 0, 0, 2, 255, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 120, 0, 0, 0, 68, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 84, 0,
+ 0, 0, 0, 0, 0, 0,
+ 100, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0,
+ 0, 0, 102, 76, 97, 121,
+ 101, 114, 79, 112, 97, 99,
+ 105, 116, 121, 0, 171, 171,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 115, 50,
+ 68, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 49, 48, 46, 49, 0, 171,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 5, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 0, 0,
+ 0, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 128, 255, 255, 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// sampler2D s2D;
+// sampler2D s2DWhite;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// fLayerOpacity c0 1
+// s2D s0 1
+// s2DWhite s1 1
+//
+
+ ps_2_0
+ def c1, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ dcl_2d s1
+ texld r0, t0, s0
+ texld r1, t0, s1
+ add r0.xyz, r0, -r1
+ add r0.xyz, r0, c1.x
+ mul r0.xyz, r0, c0.x
+ mov r0.w, r0.y
+ mov oC0, r0
+
+// approximately 7 instruction slots used (2 texture, 5 arithmetic)
+#endif
+
+const BYTE ComponentPass1ShaderPS[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 55, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 175, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 168, 0, 0, 0, 88, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 104, 0,
+ 0, 0, 0, 0, 0, 0,
+ 120, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 124, 0, 0, 0, 0, 0,
+ 0, 0, 140, 0, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 0, 0, 152, 0, 0, 0,
+ 0, 0, 0, 0, 102, 76,
+ 97, 121, 101, 114, 79, 112,
+ 97, 99, 105, 116, 121, 0,
+ 171, 171, 0, 0, 3, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 50, 68, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 87,
+ 104, 105, 116, 101, 0, 171,
+ 171, 171, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 49, 48, 46, 49, 0, 171,
+ 81, 0, 0, 5, 1, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 1, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 66, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 228, 176, 1, 8,
+ 228, 160, 2, 0, 0, 3,
+ 0, 0, 7, 128, 0, 0,
+ 228, 128, 1, 0, 228, 129,
+ 2, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 228, 128,
+ 1, 0, 0, 160, 5, 0,
+ 0, 3, 0, 0, 7, 128,
+ 0, 0, 228, 128, 0, 0,
+ 0, 160, 1, 0, 0, 2,
+ 0, 0, 8, 128, 0, 0,
+ 85, 128, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 128, 255, 255, 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// sampler2D s2D;
+// sampler2D s2DWhite;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// fLayerOpacity c0 1
+// s2D s0 1
+// s2DWhite s1 1
+//
+
+ ps_2_0
+ def c1, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ dcl_2d s1
+ texld r0, t0, s1
+ texld r1, t0, s0
+ add r0.x, -r0.y, r1.y
+ add r1.w, r0.x, c1.x
+ mul r0, r1, c0.x
+ mov oC0, r0
+
+// approximately 6 instruction slots used (2 texture, 4 arithmetic)
+#endif
+
+const BYTE ComponentPass2ShaderPS[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 55, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 175, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 168, 0, 0, 0, 88, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 104, 0,
+ 0, 0, 0, 0, 0, 0,
+ 120, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 124, 0, 0, 0, 0, 0,
+ 0, 0, 140, 0, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 0, 0, 152, 0, 0, 0,
+ 0, 0, 0, 0, 102, 76,
+ 97, 121, 101, 114, 79, 112,
+ 97, 99, 105, 116, 121, 0,
+ 171, 171, 0, 0, 3, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 50, 68, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 87,
+ 104, 105, 116, 101, 0, 171,
+ 171, 171, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 49, 48, 46, 49, 0, 171,
+ 81, 0, 0, 5, 1, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 1, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 1, 8, 228, 160, 66, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 228, 176, 0, 8,
+ 228, 160, 2, 0, 0, 3,
+ 0, 0, 1, 128, 0, 0,
+ 85, 129, 1, 0, 85, 128,
+ 2, 0, 0, 3, 1, 0,
+ 8, 128, 0, 0, 0, 128,
+ 1, 0, 0, 160, 5, 0,
+ 0, 3, 0, 0, 15, 128,
+ 1, 0, 228, 128, 0, 0,
+ 0, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 128, 255, 255, 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// sampler2D s2D;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// fLayerOpacity c0 1
+// s2D s0 1
+//
+
+ ps_2_0
+ def c1, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov r0.w, c1.x
+ mul r0, r0, c0.x
+ mov oC0, r0
+
+// approximately 4 instruction slots used (1 texture, 3 arithmetic)
+#endif
+
+const BYTE RGBShaderPS[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 43, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 127, 0,
+ 0, 0, 0, 2, 255, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 120, 0, 0, 0, 68, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 84, 0,
+ 0, 0, 0, 0, 0, 0,
+ 100, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0,
+ 0, 0, 102, 76, 97, 121,
+ 101, 114, 79, 112, 97, 99,
+ 105, 116, 121, 0, 171, 171,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 115, 50,
+ 68, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 49, 48, 46, 49, 0, 171,
+ 81, 0, 0, 5, 1, 0,
+ 15, 160, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 1, 0,
+ 0, 2, 0, 0, 8, 128,
+ 1, 0, 0, 160, 5, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 0, 0,
+ 0, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 128, 255, 255, 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// row_major float3x3 mYuvColorMatrix;
+// sampler2D s2DCb;
+// sampler2D s2DCr;
+// sampler2D s2DY;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// --------------- ----- ----
+// fLayerOpacity c0 1
+// mYuvColorMatrix c1 3
+// s2DY s0 1
+// s2DCb s1 1
+// s2DCr s2 1
+//
+
+ ps_2_0
+ def c4, -0.0627499968, -0.50195998, 1, 0
+ dcl t0.xy
+ dcl_2d s0
+ dcl_2d s1
+ dcl_2d s2
+ texld r0, t0, s0
+ texld r1, t0, s1
+ texld r2, t0, s2
+ mov r3.w, c4.z
+ add r0.x, r0.w, c4.x
+ add r0.y, r1.w, c4.y
+ add r0.z, r2.w, c4.y
+ dp3 r3.x, c1, r0
+ dp3 r3.y, c2, r0
+ dp3 r3.z, c3, r0
+ mul r0, r3, c0.x
+ mov oC0, r0
+
+// approximately 12 instruction slots used (3 texture, 9 arithmetic)
+#endif
+
+const BYTE YCbCrShaderPS[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 79, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 15, 1,
+ 0, 0, 0, 2, 255, 255,
+ 5, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 8, 1, 0, 0, 128, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 144, 0,
+ 0, 0, 0, 0, 0, 0,
+ 160, 0, 0, 0, 2, 0,
+ 1, 0, 3, 0, 6, 0,
+ 176, 0, 0, 0, 0, 0,
+ 0, 0, 192, 0, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 0, 0, 200, 0, 0, 0,
+ 0, 0, 0, 0, 216, 0,
+ 0, 0, 3, 0, 2, 0,
+ 1, 0, 0, 0, 224, 0,
+ 0, 0, 0, 0, 0, 0,
+ 240, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 248, 0, 0, 0, 0, 0,
+ 0, 0, 102, 76, 97, 121,
+ 101, 114, 79, 112, 97, 99,
+ 105, 116, 121, 0, 171, 171,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 109, 89,
+ 117, 118, 67, 111, 108, 111,
+ 114, 77, 97, 116, 114, 105,
+ 120, 0, 2, 0, 3, 0,
+ 3, 0, 3, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 50, 68, 67, 98, 0,
+ 171, 171, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 50, 68, 67, 114, 0,
+ 171, 171, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 50, 68, 89, 0, 171,
+ 171, 171, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 49, 48, 46, 49, 0, 171,
+ 81, 0, 0, 5, 4, 0,
+ 15, 160, 18, 131, 128, 189,
+ 115, 128, 0, 191, 0, 0,
+ 128, 63, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 1, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 2, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 66, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 228, 176, 1, 8,
+ 228, 160, 66, 0, 0, 3,
+ 2, 0, 15, 128, 0, 0,
+ 228, 176, 2, 8, 228, 160,
+ 1, 0, 0, 2, 3, 0,
+ 8, 128, 4, 0, 170, 160,
+ 2, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 255, 128,
+ 4, 0, 0, 160, 2, 0,
+ 0, 3, 0, 0, 2, 128,
+ 1, 0, 255, 128, 4, 0,
+ 85, 160, 2, 0, 0, 3,
+ 0, 0, 4, 128, 2, 0,
+ 255, 128, 4, 0, 85, 160,
+ 8, 0, 0, 3, 3, 0,
+ 1, 128, 1, 0, 228, 160,
+ 0, 0, 228, 128, 8, 0,
+ 0, 3, 3, 0, 2, 128,
+ 2, 0, 228, 160, 0, 0,
+ 228, 128, 8, 0, 0, 3,
+ 3, 0, 4, 128, 3, 0,
+ 228, 160, 0, 0, 228, 128,
+ 5, 0, 0, 3, 0, 0,
+ 15, 128, 3, 0, 228, 128,
+ 0, 0, 0, 160, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float4 fLayerColor;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fLayerColor c0 1
+//
+
+ ps_2_0
+ mov oC0, c0
+
+// approximately 1 instruction slot used
+#endif
+
+const BYTE SolidColorShaderPS[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 32, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 83, 0,
+ 0, 0, 0, 2, 255, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 76, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 60, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 76, 97, 121, 101, 114,
+ 67, 111, 108, 111, 114, 0,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 171, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 160, 255, 255,
+ 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float4x4 mLayerTransform;
+// float4x4 mProjection;
+// float4 vLayerQuad;
+// float4 vMaskQuad;
+// float4 vRenderTargetOffset;
+// float4 vTextureCoords;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------------- ----- ----
+// mLayerTransform c0 4
+// mProjection c4 4
+// vRenderTargetOffset c8 1
+// vTextureCoords c9 1
+// vLayerQuad c10 1
+// vMaskQuad c11 1
+//
+
+ vs_2_0
+ def c12, -0.5, 1, 0, 0
+ dcl_position v0
+ mad r0.xy, v0, c10.zwzw, c10
+ mul r1, r0.y, c1
+ mad r0, c0, r0.x, r1
+ add r0, r0, c3
+ rcp r1.x, r0.w
+ mul r1.xyz, r0, r1.x
+ mov r1.w, r0.w
+ add r2, r1, -c8
+ mad r0.zw, r2.xyxy, r2.w, c12.x
+ mul r3, r0.w, c5
+ mad r3, c4, r0.z, r3
+ mul r0.z, r2.w, r2.z
+ mad r3, c6, r0.z, r3
+ mad oPos, c7, r2.w, r3
+ add r0.xy, r0, -c11
+ rcp r0.z, c11.z
+ mul r1.x, r0.z, r0.x
+ rcp r0.x, c11.w
+ mul r1.y, r0.x, r0.y
+ mov r1.z, c12.y
+ mul oT1.xyz, r1.w, r1
+ mad oT0.xy, v0, c9.zwzw, c9
+
+// approximately 22 instruction slots used
+#endif
+
+const BYTE LayerQuadVSMask[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 84, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 34, 1,
+ 0, 0, 0, 2, 254, 255,
+ 6, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 27, 1, 0, 0, 148, 0,
+ 0, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 164, 0,
+ 0, 0, 0, 0, 0, 0,
+ 180, 0, 0, 0, 2, 0,
+ 4, 0, 4, 0, 0, 0,
+ 164, 0, 0, 0, 0, 0,
+ 0, 0, 192, 0, 0, 0,
+ 2, 0, 10, 0, 1, 0,
+ 0, 0, 204, 0, 0, 0,
+ 0, 0, 0, 0, 220, 0,
+ 0, 0, 2, 0, 11, 0,
+ 1, 0, 0, 0, 204, 0,
+ 0, 0, 0, 0, 0, 0,
+ 230, 0, 0, 0, 2, 0,
+ 8, 0, 1, 0, 0, 0,
+ 252, 0, 0, 0, 0, 0,
+ 0, 0, 12, 1, 0, 0,
+ 2, 0, 9, 0, 1, 0,
+ 0, 0, 204, 0, 0, 0,
+ 0, 0, 0, 0, 109, 76,
+ 97, 121, 101, 114, 84, 114,
+ 97, 110, 115, 102, 111, 114,
+ 109, 0, 3, 0, 3, 0,
+ 4, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 109, 80, 114, 111, 106, 101,
+ 99, 116, 105, 111, 110, 0,
+ 118, 76, 97, 121, 101, 114,
+ 81, 117, 97, 100, 0, 171,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 118, 77,
+ 97, 115, 107, 81, 117, 97,
+ 100, 0, 118, 82, 101, 110,
+ 100, 101, 114, 84, 97, 114,
+ 103, 101, 116, 79, 102, 102,
+ 115, 101, 116, 0, 171, 171,
+ 1, 0, 3, 0, 1, 0,
+ 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 118, 84,
+ 101, 120, 116, 117, 114, 101,
+ 67, 111, 111, 114, 100, 115,
+ 0, 118, 115, 95, 50, 95,
+ 48, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114,
+ 32, 49, 48, 46, 49, 0,
+ 171, 171, 81, 0, 0, 5,
+ 12, 0, 15, 160, 0, 0,
+ 0, 191, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 4, 0, 0, 4,
+ 0, 0, 3, 128, 0, 0,
+ 228, 144, 10, 0, 238, 160,
+ 10, 0, 228, 160, 5, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 85, 128, 1, 0,
+ 228, 160, 4, 0, 0, 4,
+ 0, 0, 15, 128, 0, 0,
+ 228, 160, 0, 0, 0, 128,
+ 1, 0, 228, 128, 2, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 3, 0,
+ 228, 160, 6, 0, 0, 2,
+ 1, 0, 1, 128, 0, 0,
+ 255, 128, 5, 0, 0, 3,
+ 1, 0, 7, 128, 0, 0,
+ 228, 128, 1, 0, 0, 128,
+ 1, 0, 0, 2, 1, 0,
+ 8, 128, 0, 0, 255, 128,
+ 2, 0, 0, 3, 2, 0,
+ 15, 128, 1, 0, 228, 128,
+ 8, 0, 228, 161, 4, 0,
+ 0, 4, 0, 0, 12, 128,
+ 2, 0, 68, 128, 2, 0,
+ 255, 128, 12, 0, 0, 160,
+ 5, 0, 0, 3, 3, 0,
+ 15, 128, 0, 0, 255, 128,
+ 5, 0, 228, 160, 4, 0,
+ 0, 4, 3, 0, 15, 128,
+ 4, 0, 228, 160, 0, 0,
+ 170, 128, 3, 0, 228, 128,
+ 5, 0, 0, 3, 0, 0,
+ 4, 128, 2, 0, 255, 128,
+ 2, 0, 170, 128, 4, 0,
+ 0, 4, 3, 0, 15, 128,
+ 6, 0, 228, 160, 0, 0,
+ 170, 128, 3, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 15, 192, 7, 0, 228, 160,
+ 2, 0, 255, 128, 3, 0,
+ 228, 128, 2, 0, 0, 3,
+ 0, 0, 3, 128, 0, 0,
+ 228, 128, 11, 0, 228, 161,
+ 6, 0, 0, 2, 0, 0,
+ 4, 128, 11, 0, 170, 160,
+ 5, 0, 0, 3, 1, 0,
+ 1, 128, 0, 0, 170, 128,
+ 0, 0, 0, 128, 6, 0,
+ 0, 2, 0, 0, 1, 128,
+ 11, 0, 255, 160, 5, 0,
+ 0, 3, 1, 0, 2, 128,
+ 0, 0, 0, 128, 0, 0,
+ 85, 128, 1, 0, 0, 2,
+ 1, 0, 4, 128, 12, 0,
+ 85, 160, 5, 0, 0, 3,
+ 1, 0, 7, 224, 1, 0,
+ 255, 128, 1, 0, 228, 128,
+ 4, 0, 0, 4, 0, 0,
+ 3, 224, 0, 0, 228, 144,
+ 9, 0, 238, 160, 9, 0,
+ 228, 160, 255, 255, 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// sampler2D s2D;
+// sampler2D s2DMask;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// fLayerOpacity c0 1
+// s2D s0 1
+// s2DMask s1 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl t1.xyz
+ dcl_2d s0
+ dcl_2d s1
+ rcp r0.w, t1.z
+ mul r0.xy, r0.w, t1
+ texld r0, r0, s1
+ texld r1, t0, s0
+ mul r1, r1, c0.x
+ mul r0, r0.w, r1
+ mov oC0, r0
+
+// approximately 7 instruction slots used (2 texture, 5 arithmetic)
+#endif
+
+const BYTE RGBAShaderPSMask[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 54, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 171, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 164, 0, 0, 0, 88, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 104, 0,
+ 0, 0, 0, 0, 0, 0,
+ 120, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 124, 0, 0, 0, 0, 0,
+ 0, 0, 140, 0, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 0, 0, 148, 0, 0, 0,
+ 0, 0, 0, 0, 102, 76,
+ 97, 121, 101, 114, 79, 112,
+ 97, 99, 105, 116, 121, 0,
+ 171, 171, 0, 0, 3, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 50, 68, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 77,
+ 97, 115, 107, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 49, 48, 46, 49,
+ 0, 171, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 128, 1, 0,
+ 7, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 1, 8,
+ 15, 160, 6, 0, 0, 2,
+ 0, 0, 8, 128, 1, 0,
+ 170, 176, 5, 0, 0, 3,
+ 0, 0, 3, 128, 0, 0,
+ 255, 128, 1, 0, 228, 176,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 128,
+ 1, 8, 228, 160, 66, 0,
+ 0, 3, 1, 0, 15, 128,
+ 0, 0, 228, 176, 0, 8,
+ 228, 160, 5, 0, 0, 3,
+ 1, 0, 15, 128, 1, 0,
+ 228, 128, 0, 0, 0, 160,
+ 5, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 255, 128,
+ 1, 0, 228, 128, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// sampler2D s2D;
+// sampler2D s2DMask;
+// sampler2D s2DWhite;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// fLayerOpacity c0 1
+// s2D s0 1
+// s2DWhite s1 1
+// s2DMask s2 1
+//
+
+ ps_2_0
+ def c1, 1, 0, 0, 0
+ dcl t0.xy
+ dcl t1.xyz
+ dcl_2d s0
+ dcl_2d s1
+ dcl_2d s2
+ rcp r0.w, t1.z
+ mul r0.xy, r0.w, t1
+ texld r1, t0, s0
+ texld r2, t0, s1
+ texld r0, r0, s2
+ add r0.xyz, r1, -r2
+ add r0.xyz, r0, c1.x
+ mul r0.xyz, r0, c0.x
+ mul r0.xyz, r0.w, r0
+ mov r0.w, r0.y
+ mov oC0, r0
+
+// approximately 11 instruction slots used (3 texture, 8 arithmetic)
+#endif
+
+const BYTE ComponentPass1ShaderPSMask[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 66, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 219, 0,
+ 0, 0, 0, 2, 255, 255,
+ 4, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 212, 0, 0, 0, 108, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 124, 0,
+ 0, 0, 0, 0, 0, 0,
+ 140, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 144, 0, 0, 0, 0, 0,
+ 0, 0, 160, 0, 0, 0,
+ 3, 0, 2, 0, 1, 0,
+ 0, 0, 168, 0, 0, 0,
+ 0, 0, 0, 0, 184, 0,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 196, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 76, 97, 121, 101, 114,
+ 79, 112, 97, 99, 105, 116,
+ 121, 0, 171, 171, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 115, 50,
+ 68, 77, 97, 115, 107, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 115, 50,
+ 68, 87, 104, 105, 116, 101,
+ 0, 171, 171, 171, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 49, 48, 46, 49,
+ 0, 171, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 128, 1, 0,
+ 7, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 1, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 2, 8,
+ 15, 160, 6, 0, 0, 2,
+ 0, 0, 8, 128, 1, 0,
+ 170, 176, 5, 0, 0, 3,
+ 0, 0, 3, 128, 0, 0,
+ 255, 128, 1, 0, 228, 176,
+ 66, 0, 0, 3, 1, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 66, 0,
+ 0, 3, 2, 0, 15, 128,
+ 0, 0, 228, 176, 1, 8,
+ 228, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 128, 2, 8, 228, 160,
+ 2, 0, 0, 3, 0, 0,
+ 7, 128, 1, 0, 228, 128,
+ 2, 0, 228, 129, 2, 0,
+ 0, 3, 0, 0, 7, 128,
+ 0, 0, 228, 128, 1, 0,
+ 0, 160, 5, 0, 0, 3,
+ 0, 0, 7, 128, 0, 0,
+ 228, 128, 0, 0, 0, 160,
+ 5, 0, 0, 3, 0, 0,
+ 7, 128, 0, 0, 255, 128,
+ 0, 0, 228, 128, 1, 0,
+ 0, 2, 0, 0, 8, 128,
+ 0, 0, 85, 128, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// sampler2D s2D;
+// sampler2D s2DMask;
+// sampler2D s2DWhite;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// fLayerOpacity c0 1
+// s2D s0 1
+// s2DWhite s1 1
+// s2DMask s2 1
+//
+
+ ps_2_0
+ def c1, 1, 0, 0, 0
+ dcl t0.xy
+ dcl t1.xyz
+ dcl_2d s0
+ dcl_2d s1
+ dcl_2d s2
+ rcp r0.w, t1.z
+ mul r0.xy, r0.w, t1
+ texld r1, t0, s1
+ texld r2, t0, s0
+ texld r0, r0, s2
+ add r0.x, -r1.y, r2.y
+ add r2.w, r0.x, c1.x
+ mul r1, r2, c0.x
+ mul r0, r0.w, r1
+ mov oC0, r0
+
+// approximately 10 instruction slots used (3 texture, 7 arithmetic)
+#endif
+
+const BYTE ComponentPass2ShaderPSMask[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 66, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 219, 0,
+ 0, 0, 0, 2, 255, 255,
+ 4, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 212, 0, 0, 0, 108, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 124, 0,
+ 0, 0, 0, 0, 0, 0,
+ 140, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 144, 0, 0, 0, 0, 0,
+ 0, 0, 160, 0, 0, 0,
+ 3, 0, 2, 0, 1, 0,
+ 0, 0, 168, 0, 0, 0,
+ 0, 0, 0, 0, 184, 0,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 196, 0,
+ 0, 0, 0, 0, 0, 0,
+ 102, 76, 97, 121, 101, 114,
+ 79, 112, 97, 99, 105, 116,
+ 121, 0, 171, 171, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 115, 50,
+ 68, 77, 97, 115, 107, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 115, 50,
+ 68, 87, 104, 105, 116, 101,
+ 0, 171, 171, 171, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 49, 48, 46, 49,
+ 0, 171, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 128, 1, 0,
+ 7, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 1, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 2, 8,
+ 15, 160, 6, 0, 0, 2,
+ 0, 0, 8, 128, 1, 0,
+ 170, 176, 5, 0, 0, 3,
+ 0, 0, 3, 128, 0, 0,
+ 255, 128, 1, 0, 228, 176,
+ 66, 0, 0, 3, 1, 0,
+ 15, 128, 0, 0, 228, 176,
+ 1, 8, 228, 160, 66, 0,
+ 0, 3, 2, 0, 15, 128,
+ 0, 0, 228, 176, 0, 8,
+ 228, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 128, 2, 8, 228, 160,
+ 2, 0, 0, 3, 0, 0,
+ 1, 128, 1, 0, 85, 129,
+ 2, 0, 85, 128, 2, 0,
+ 0, 3, 2, 0, 8, 128,
+ 0, 0, 0, 128, 1, 0,
+ 0, 160, 5, 0, 0, 3,
+ 1, 0, 15, 128, 2, 0,
+ 228, 128, 0, 0, 0, 160,
+ 5, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 255, 128,
+ 1, 0, 228, 128, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// sampler2D s2D;
+// sampler2D s2DMask;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// fLayerOpacity c0 1
+// s2D s0 1
+// s2DMask s1 1
+//
+
+ ps_2_0
+ def c1, 1, 0, 0, 0
+ dcl t0.xy
+ dcl t1.xyz
+ dcl_2d s0
+ dcl_2d s1
+ rcp r0.w, t1.z
+ mul r0.xy, r0.w, t1
+ texld r1, t0, s0
+ texld r0, r0, s1
+ mov r1.w, c1.x
+ mul r1, r1, c0.x
+ mul r0, r0.w, r1
+ mov oC0, r0
+
+// approximately 8 instruction slots used (2 texture, 6 arithmetic)
+#endif
+
+const BYTE RGBShaderPSMask[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 54, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 171, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 164, 0, 0, 0, 88, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 104, 0,
+ 0, 0, 0, 0, 0, 0,
+ 120, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 124, 0, 0, 0, 0, 0,
+ 0, 0, 140, 0, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 0, 0, 148, 0, 0, 0,
+ 0, 0, 0, 0, 102, 76,
+ 97, 121, 101, 114, 79, 112,
+ 97, 99, 105, 116, 121, 0,
+ 171, 171, 0, 0, 3, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 50, 68, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 77,
+ 97, 115, 107, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 49, 48, 46, 49,
+ 0, 171, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 128, 63, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 128, 1, 0,
+ 7, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 1, 8,
+ 15, 160, 6, 0, 0, 2,
+ 0, 0, 8, 128, 1, 0,
+ 170, 176, 5, 0, 0, 3,
+ 0, 0, 3, 128, 0, 0,
+ 255, 128, 1, 0, 228, 176,
+ 66, 0, 0, 3, 1, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 1, 8,
+ 228, 160, 1, 0, 0, 2,
+ 1, 0, 8, 128, 1, 0,
+ 0, 160, 5, 0, 0, 3,
+ 1, 0, 15, 128, 1, 0,
+ 228, 128, 0, 0, 0, 160,
+ 5, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 255, 128,
+ 1, 0, 228, 128, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float fLayerOpacity;
+// row_major float3x3 mYuvColorMatrix;
+// sampler2D s2DCb;
+// sampler2D s2DCr;
+// sampler2D s2DMask;
+// sampler2D s2DY;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// --------------- ----- ----
+// fLayerOpacity c0 1
+// mYuvColorMatrix c1 3
+// s2DY s0 1
+// s2DCb s1 1
+// s2DCr s2 1
+// s2DMask s3 1
+//
+
+ ps_2_0
+ def c4, -0.0627499968, -0.50195998, 1, 0
+ dcl t0.xy
+ dcl t1.xyz
+ dcl_2d s0
+ dcl_2d s1
+ dcl_2d s2
+ dcl_2d s3
+ rcp r0.w, t1.z
+ mul r0.xy, r0.w, t1
+ texld r1, t0, s0
+ texld r2, t0, s1
+ texld r3, t0, s2
+ texld r0, r0, s3
+ mov r4.w, c4.z
+ add r0.x, r1.w, c4.x
+ add r0.y, r2.w, c4.y
+ add r0.z, r3.w, c4.y
+ dp3 r4.x, c1, r0
+ dp3 r4.y, c2, r0
+ dp3 r4.z, c3, r0
+ mul r1, r4, c0.x
+ mul r0, r0.w, r1
+ mov oC0, r0
+
+// approximately 16 instruction slots used (4 texture, 12 arithmetic)
+#endif
+
+const BYTE YCbCrShaderPSMask[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 90, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 59, 1,
+ 0, 0, 0, 2, 255, 255,
+ 6, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 52, 1, 0, 0, 148, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 164, 0,
+ 0, 0, 0, 0, 0, 0,
+ 180, 0, 0, 0, 2, 0,
+ 1, 0, 3, 0, 6, 0,
+ 196, 0, 0, 0, 0, 0,
+ 0, 0, 212, 0, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 0, 0, 220, 0, 0, 0,
+ 0, 0, 0, 0, 236, 0,
+ 0, 0, 3, 0, 2, 0,
+ 1, 0, 0, 0, 244, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 1, 0, 0, 3, 0,
+ 3, 0, 1, 0, 0, 0,
+ 12, 1, 0, 0, 0, 0,
+ 0, 0, 28, 1, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 36, 1, 0, 0,
+ 0, 0, 0, 0, 102, 76,
+ 97, 121, 101, 114, 79, 112,
+ 97, 99, 105, 116, 121, 0,
+ 171, 171, 0, 0, 3, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 109, 89, 117, 118, 67, 111,
+ 108, 111, 114, 77, 97, 116,
+ 114, 105, 120, 0, 2, 0,
+ 3, 0, 3, 0, 3, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 67,
+ 98, 0, 171, 171, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 67,
+ 114, 0, 171, 171, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 77,
+ 97, 115, 107, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 115, 50, 68, 89,
+ 0, 171, 171, 171, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 49, 48, 46, 49,
+ 0, 171, 81, 0, 0, 5,
+ 4, 0, 15, 160, 18, 131,
+ 128, 189, 115, 128, 0, 191,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 128, 1, 0,
+ 7, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 1, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 2, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 3, 8,
+ 15, 160, 6, 0, 0, 2,
+ 0, 0, 8, 128, 1, 0,
+ 170, 176, 5, 0, 0, 3,
+ 0, 0, 3, 128, 0, 0,
+ 255, 128, 1, 0, 228, 176,
+ 66, 0, 0, 3, 1, 0,
+ 15, 128, 0, 0, 228, 176,
+ 0, 8, 228, 160, 66, 0,
+ 0, 3, 2, 0, 15, 128,
+ 0, 0, 228, 176, 1, 8,
+ 228, 160, 66, 0, 0, 3,
+ 3, 0, 15, 128, 0, 0,
+ 228, 176, 2, 8, 228, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 128,
+ 3, 8, 228, 160, 1, 0,
+ 0, 2, 4, 0, 8, 128,
+ 4, 0, 170, 160, 2, 0,
+ 0, 3, 0, 0, 1, 128,
+ 1, 0, 255, 128, 4, 0,
+ 0, 160, 2, 0, 0, 3,
+ 0, 0, 2, 128, 2, 0,
+ 255, 128, 4, 0, 85, 160,
+ 2, 0, 0, 3, 0, 0,
+ 4, 128, 3, 0, 255, 128,
+ 4, 0, 85, 160, 8, 0,
+ 0, 3, 4, 0, 1, 128,
+ 1, 0, 228, 160, 0, 0,
+ 228, 128, 8, 0, 0, 3,
+ 4, 0, 2, 128, 2, 0,
+ 228, 160, 0, 0, 228, 128,
+ 8, 0, 0, 3, 4, 0,
+ 4, 128, 3, 0, 228, 160,
+ 0, 0, 228, 128, 5, 0,
+ 0, 3, 1, 0, 15, 128,
+ 4, 0, 228, 128, 0, 0,
+ 0, 160, 5, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 255, 128, 1, 0, 228, 128,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+// Parameters:
+//
+// float4 fLayerColor;
+// sampler2D s2DMask;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// fLayerColor c0 1
+// s2DMask s0 1
+//
+
+ ps_2_0
+ dcl t1.xyz
+ dcl_2d s0
+ rcp r0.w, t1.z
+ mul r0.xy, r0.w, t1
+ texld r0, r0, s0
+ mul r0, r0.w, c0
+ mov oC0, r0
+
+// approximately 5 instruction slots used (1 texture, 4 arithmetic)
+#endif
+
+const BYTE SolidColorShaderPSMask[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 43, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 127, 0,
+ 0, 0, 0, 2, 255, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 120, 0, 0, 0, 68, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0,
+ 96, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0,
+ 0, 0, 102, 76, 97, 121,
+ 101, 114, 67, 111, 108, 111,
+ 114, 0, 1, 0, 3, 0,
+ 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 115, 50, 68, 77, 97, 115,
+ 107, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 49, 48, 46, 49, 0, 171,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 1, 0, 7, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 6, 0, 0, 2, 0, 0,
+ 8, 128, 1, 0, 170, 176,
+ 5, 0, 0, 3, 0, 0,
+ 3, 128, 0, 0, 255, 128,
+ 1, 0, 228, 176, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 0, 8,
+ 228, 160, 5, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 255, 128, 0, 0, 228, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
diff --git a/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl
new file mode 100644
index 000000000..1f3a812f3
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl
@@ -0,0 +1,242 @@
+float4x4 mLayerTransform;
+float4 vRenderTargetOffset;
+float4x4 mProjection;
+
+typedef float4 rect;
+rect vTextureCoords;
+rect vLayerQuad;
+rect vMaskQuad;
+
+texture tex0;
+sampler s2D;
+sampler s2DWhite;
+sampler s2DY;
+sampler s2DCb;
+sampler s2DCr;
+sampler s2DMask;
+
+
+float fLayerOpacity;
+float4 fLayerColor;
+row_major float3x3 mYuvColorMatrix : register(ps, c1);
+
+struct VS_INPUT {
+ float4 vPosition : POSITION;
+};
+
+struct VS_OUTPUT {
+ float4 vPosition : POSITION;
+ float2 vTexCoords : TEXCOORD0;
+};
+
+struct VS_OUTPUT_MASK {
+ float4 vPosition : POSITION;
+ float2 vTexCoords : TEXCOORD0;
+ float3 vMaskCoords : TEXCOORD1;
+};
+
+VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex)
+{
+ VS_OUTPUT outp;
+ outp.vPosition = aVertex.vPosition;
+
+ // We use 4 component floats to uniquely describe a rectangle, by the structure
+ // of x, y, width, height. This allows us to easily generate the 4 corners
+ // of any rectangle from the 4 corners of the 0,0-1,1 quad that we use as the
+ // stream source for our LayerQuad vertex shader. We do this by doing:
+ // Xout = x + Xin * width
+ // Yout = y + Yin * height
+ float2 position = vLayerQuad.xy;
+ float2 size = vLayerQuad.zw;
+ outp.vPosition.x = position.x + outp.vPosition.x * size.x;
+ outp.vPosition.y = position.y + outp.vPosition.y * size.y;
+
+ outp.vPosition = mul(mLayerTransform, outp.vPosition);
+ outp.vPosition.xyz /= outp.vPosition.w;
+ outp.vPosition = outp.vPosition - vRenderTargetOffset;
+ outp.vPosition.xyz *= outp.vPosition.w;
+
+ // adjust our vertices to match d3d9's pixel coordinate system
+ // which has pixel centers at integer locations
+ outp.vPosition.xy -= 0.5;
+
+ outp.vPosition = mul(mProjection, outp.vPosition);
+
+ position = vTextureCoords.xy;
+ size = vTextureCoords.zw;
+ outp.vTexCoords.x = position.x + aVertex.vPosition.x * size.x;
+ outp.vTexCoords.y = position.y + aVertex.vPosition.y * size.y;
+
+ return outp;
+}
+
+VS_OUTPUT_MASK LayerQuadVSMask(const VS_INPUT aVertex)
+{
+ VS_OUTPUT_MASK outp;
+ float4 position = float4(0, 0, 0, 1);
+
+ // We use 4 component floats to uniquely describe a rectangle, by the structure
+ // of x, y, width, height. This allows us to easily generate the 4 corners
+ // of any rectangle from the 4 corners of the 0,0-1,1 quad that we use as the
+ // stream source for our LayerQuad vertex shader. We do this by doing:
+ // Xout = x + Xin * width
+ // Yout = y + Yin * height
+ float2 size = vLayerQuad.zw;
+ position.x = vLayerQuad.x + aVertex.vPosition.x * size.x;
+ position.y = vLayerQuad.y + aVertex.vPosition.y * size.y;
+
+ position = mul(mLayerTransform, position);
+ outp.vPosition.w = position.w;
+ outp.vPosition.xyz = position.xyz / position.w;
+ outp.vPosition = outp.vPosition - vRenderTargetOffset;
+ outp.vPosition.xyz *= outp.vPosition.w;
+
+ // adjust our vertices to match d3d9's pixel coordinate system
+ // which has pixel centers at integer locations
+ outp.vPosition.xy -= 0.5;
+
+ outp.vPosition = mul(mProjection, outp.vPosition);
+
+ // calculate the position on the mask texture
+ outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
+ outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
+ // correct for perspective correct interpolation, see comment in D3D11 shader
+ outp.vMaskCoords.z = 1;
+ outp.vMaskCoords *= position.w;
+
+ size = vTextureCoords.zw;
+ outp.vTexCoords.x = vTextureCoords.x + aVertex.vPosition.x * size.x;
+ outp.vTexCoords.y = vTextureCoords.y + aVertex.vPosition.y * size.y;
+
+ return outp;
+}
+
+float4 ComponentPass1Shader(const VS_OUTPUT aVertex) : COLOR
+{
+ float4 src = tex2D(s2D, aVertex.vTexCoords);
+ float4 alphas = 1.0 - tex2D(s2DWhite, aVertex.vTexCoords) + src;
+ alphas.a = alphas.g;
+ return alphas * fLayerOpacity;
+}
+
+float4 ComponentPass2Shader(const VS_OUTPUT aVertex) : COLOR
+{
+ float4 src = tex2D(s2D, aVertex.vTexCoords);
+ float4 alphas = 1.0 - tex2D(s2DWhite, aVertex.vTexCoords) + src;
+ src.a = alphas.g;
+ return src * fLayerOpacity;
+}
+
+float4 RGBAShader(const VS_OUTPUT aVertex) : COLOR
+{
+ return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity;
+}
+
+float4 RGBShader(const VS_OUTPUT aVertex) : COLOR
+{
+ float4 result;
+ result = tex2D(s2D, aVertex.vTexCoords);
+ result.a = 1.0;
+ return result * fLayerOpacity;
+}
+
+/* From Rec601:
+[R] [1.1643835616438356, 0.0, 1.5960267857142858] [ Y - 16]
+[G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708] x [Cb - 128]
+[B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [Cr - 128]
+
+For [0,1] instead of [0,255], and to 5 places:
+[R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275]
+[G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196]
+[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
+
+From Rec709:
+[R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [ Y - 16]
+[G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444] x [Cb - 128]
+[B] [1.1643835616438356, 2.1124017857142854, 0.0] [Cr - 128]
+
+For [0,1] instead of [0,255], and to 5 places:
+[R] [1.16438, 0.00000, 1.79274] [ Y - 0.06275]
+[G] = [1.16438, -0.21325, -0.53291] x [Cb - 0.50196]
+[B] [1.16438, 2.11240, 0.00000] [Cr - 0.50196]
+*/
+float4 YCbCrShader(const VS_OUTPUT aVertex) : COLOR
+{
+ float3 yuv;
+ float4 color;
+
+ yuv.x = tex2D(s2DY, aVertex.vTexCoords).a - 0.06275;
+ yuv.y = tex2D(s2DCb, aVertex.vTexCoords).a - 0.50196;
+ yuv.z = tex2D(s2DCr, aVertex.vTexCoords).a - 0.50196;
+
+ color.rgb = mul(mYuvColorMatrix, yuv);
+ color.a = 1.0f;
+
+ return color * fLayerOpacity;
+}
+
+float4 SolidColorShader(const VS_OUTPUT aVertex) : COLOR
+{
+ return fLayerColor;
+}
+
+float4 ComponentPass1ShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
+{
+ float4 src = tex2D(s2D, aVertex.vTexCoords);
+ float4 alphas = 1.0 - tex2D(s2DWhite, aVertex.vTexCoords) + src;
+ alphas.a = alphas.g;
+ float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
+ float mask = tex2D(s2DMask, maskCoords).a;
+ return alphas * fLayerOpacity * mask;
+}
+
+float4 ComponentPass2ShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
+{
+ float4 src = tex2D(s2D, aVertex.vTexCoords);
+ float4 alphas = 1.0 - tex2D(s2DWhite, aVertex.vTexCoords) + src;
+ src.a = alphas.g;
+ float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
+ float mask = tex2D(s2DMask, maskCoords).a;
+ return src * fLayerOpacity * mask;
+}
+
+float4 RGBAShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
+{
+ float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
+ float mask = tex2D(s2DMask, maskCoords).a;
+ return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity * mask;
+}
+
+float4 RGBShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
+{
+ float4 result;
+ result = tex2D(s2D, aVertex.vTexCoords);
+ result.a = 1.0;
+ float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
+ float mask = tex2D(s2DMask, maskCoords).a;
+ return result * fLayerOpacity * mask;
+}
+
+float4 YCbCrShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
+{
+ float3 yuv;
+ float4 color;
+
+ yuv.x = tex2D(s2DY, aVertex.vTexCoords).a - 0.06275;
+ yuv.y = tex2D(s2DCb, aVertex.vTexCoords).a - 0.50196;
+ yuv.z = tex2D(s2DCr, aVertex.vTexCoords).a - 0.50196;
+
+ color.rgb = mul((float3x3)mYuvColorMatrix, yuv);
+ color.a = 1.0f;
+
+ float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
+ float mask = tex2D(s2DMask, maskCoords).a;
+ return color * fLayerOpacity * mask;
+}
+
+float4 SolidColorShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR
+{
+ float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
+ float mask = tex2D(s2DMask, maskCoords).a;
+ return fLayerColor * mask;
+}
diff --git a/gfx/layers/d3d9/Nv3DVUtils.cpp b/gfx/layers/d3d9/Nv3DVUtils.cpp
new file mode 100644
index 000000000..72638228f
--- /dev/null
+++ b/gfx/layers/d3d9/Nv3DVUtils.cpp
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/. */
+
+#include "mozilla/DebugOnly.h"
+
+#include "nsIServiceManager.h"
+#include "nsIConsoleService.h"
+#include <initguid.h>
+#include "Nv3DVUtils.h"
+
+DEFINE_GUID(CLSID_NV3DVStreaming,
+0xf7747266, 0x777d, 0x4f61, 0xa1, 0x75, 0xdd, 0x5a, 0xdf, 0x1e, 0x37, 0xdf);
+
+DEFINE_GUID(IID_INV3DVStreaming,
+0xf98f9bb2, 0xb914, 0x4d44, 0x98, 0xfa, 0x6e, 0x37, 0x85, 0x16, 0x98, 0x55);
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * Constructor and Destructor
+ */
+Nv3DVUtils::Nv3DVUtils()
+ : m3DVStreaming (nullptr)
+{
+}
+
+Nv3DVUtils::~Nv3DVUtils()
+{
+ UnInitialize();
+}
+
+
+// Silence spurious warnings!
+#if defined(WARNING) || defined WARN_IF_FALSE
+#error We shouldn't be redefining these!
+#endif
+// Uncomment these to enable spurious warnings.
+//#define WARNING(str) NS_WARNING(str)
+//#define WARN_IF_FALSE(b, str) NS_WARNING_ASSERTION(b, str)
+#define WARNING(str)
+#define WARN_IF_FALSE(b, str)
+
+/**
+ * Initializes the Nv3DVUtils object.
+ */
+void
+Nv3DVUtils::Initialize()
+{
+ /*
+ * Detect if 3D Streaming object is already loaded. Do nothing in that case.
+ */
+ if (m3DVStreaming) {
+ WARNING("Nv3DVStreaming COM object already instantiated.\n");
+ return;
+ }
+
+ /*
+ * Create the COM object. If we fail at any stage, just return
+ */
+ HRESULT hr = CoCreateInstance(CLSID_NV3DVStreaming, nullptr, CLSCTX_INPROC_SERVER, IID_INV3DVStreaming, (void**)(getter_AddRefs(m3DVStreaming)));
+ if (FAILED(hr) || !m3DVStreaming) {
+ WARNING("Nv3DVStreaming CoCreateInstance failed (disabled).");
+ return;
+ }
+
+ /*
+ * Initialize the object. Note that m3DVStreaming cannot be nullptr at this point.
+ */
+ bool bRetVal = m3DVStreaming->Nv3DVInitialize();
+
+ if (!bRetVal) {
+ WARNING("Nv3DVStreaming Nv3DVInitialize failed!");
+ return;
+ }
+}
+
+/**
+ * Release resources used by the COM Object, and then release
+ * the COM Object (nsRefPtr gets released by setting to nullptr)
+ *
+ */
+void
+Nv3DVUtils::UnInitialize()
+{
+ if (m3DVStreaming) {
+ m3DVStreaming->Nv3DVRelease();
+ }
+}
+
+/**
+ * Sets the device info, along with any other initialization that is needed after device creation
+ * Pass the D3D9 device pointer is an IUnknown input argument.
+ */
+void
+Nv3DVUtils::SetDeviceInfo(IUnknown *devUnknown)
+{
+ if (!devUnknown) {
+ WARNING("D3D Device Pointer (IUnknown) is nullptr.\n");
+ return;
+ }
+
+ if (!m3DVStreaming) {
+ return;
+ }
+
+ bool rv = m3DVStreaming->Nv3DVSetDevice(devUnknown);
+ if (!rv) {
+ WARNING("Nv3DVStreaming Nv3DVControl failed!");
+ return;
+ }
+
+ rv = m3DVStreaming->Nv3DVControl(NV_STEREO_MODE_RIGHT_LEFT, true, FIREFOX_3DV_APP_HANDLE);
+ WARN_IF_FALSE(rv, "Nv3DVStreaming Nv3DVControl failed!");
+}
+
+/*
+ * Send Stereo Control Information. Used mainly to re-route
+ * calls from ImageLayerD3D9 to the 3DV COM object
+ */
+void
+Nv3DVUtils::SendNv3DVControl(Nv_Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle)
+{
+ if (!m3DVStreaming)
+ return;
+
+ DebugOnly<bool> rv = m3DVStreaming->Nv3DVControl(eStereoMode, bEnableStereo, dw3DVAppHandle);
+ WARN_IF_FALSE(rv, "Nv3DVStreaming Nv3DVControl failed!");
+}
+
+/*
+ * Send Stereo Metadata. Used mainly to re-route calls
+ * from ImageLayerD3D9 to the 3DV COM object
+ */
+void
+Nv3DVUtils::SendNv3DVMetaData(unsigned int dwWidth, unsigned int dwHeight, HANDLE hSrcLuma, HANDLE hDst)
+{
+ if (!m3DVStreaming)
+ return;
+
+ DebugOnly<bool> rv = m3DVStreaming->Nv3DVMetaData((DWORD)dwWidth, (DWORD)dwHeight, hSrcLuma, hDst);
+ WARN_IF_FALSE(rv, "Nv3DVStreaming Nv3DVMetaData failed!");
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
diff --git a/gfx/layers/d3d9/Nv3DVUtils.h b/gfx/layers/d3d9/Nv3DVUtils.h
new file mode 100644
index 000000000..0712dd888
--- /dev/null
+++ b/gfx/layers/d3d9/Nv3DVUtils.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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 GFX_NV3DVUTILS_H
+#define GFX_NV3DVUTILS_H
+
+#include "Layers.h"
+#include <windows.h>
+#include <d3d9.h>
+
+namespace mozilla {
+namespace layers {
+
+#define FIREFOX_3DV_APP_HANDLE 0xECB992B6
+
+enum Nv_Stereo_Mode {
+ NV_STEREO_MODE_LEFT_RIGHT = 0,
+ NV_STEREO_MODE_RIGHT_LEFT = 1,
+ NV_STEREO_MODE_TOP_BOTTOM = 2,
+ NV_STEREO_MODE_BOTTOM_TOP = 3,
+ NV_STEREO_MODE_MONO = 4,
+ NV_STEREO_MODE_LAST = 5
+};
+
+class INv3DVStreaming : public IUnknown {
+
+public:
+ virtual bool Nv3DVInitialize() = 0;
+ virtual bool Nv3DVRelease() = 0;
+ virtual bool Nv3DVSetDevice(IUnknown* pDevice) = 0;
+ virtual bool Nv3DVControl(Nv_Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle) = 0;
+ virtual bool Nv3DVMetaData(DWORD dwWidth, DWORD dwHeight, HANDLE hSrcLuma, HANDLE hDst) = 0;
+};
+
+/*
+ * Nv3DVUtils class
+ */
+class Nv3DVUtils {
+
+public:
+ Nv3DVUtils();
+ ~Nv3DVUtils();
+
+ /*
+ * Initializes the Nv3DVUtils object.
+ */
+ void Initialize();
+
+ /*
+ * Release any resources if needed
+ *
+ */
+ void UnInitialize();
+
+ /*
+ * Sets the device info, along with any other initialization that is needed after device creation
+ * Pass the D3D9 device pointer is an IUnknown input argument
+ */
+ void SetDeviceInfo(IUnknown *devUnknown);
+
+ /*
+ * Send Stereo Control Information. Used mainly to re-route
+ * calls from ImageLayerD3D9 to the 3DV COM object
+ */
+ void SendNv3DVControl(Nv_Stereo_Mode eStereoMode, bool bEnableStereo, DWORD dw3DVAppHandle);
+
+ /*
+ * Send Stereo Metadata. Used mainly to re-route calls
+ * from ImageLayerD3D9 to the 3DV COM object
+ */
+ void SendNv3DVMetaData(unsigned int dwWidth, unsigned int dwHeight, HANDLE hSrcLuma, HANDLE hDst);
+
+private:
+
+ /* Nv3DVStreaming interface pointer */
+ RefPtr<INv3DVStreaming> m3DVStreaming;
+
+};
+
+
+} // namespace layers
+} // namespace mozilla
+
+#endif /* GFX_NV3DVUTILS_H */
diff --git a/gfx/layers/d3d9/ReadbackLayerD3D9.h b/gfx/layers/d3d9/ReadbackLayerD3D9.h
new file mode 100644
index 000000000..5d3a7fd1e
--- /dev/null
+++ b/gfx/layers/d3d9/ReadbackLayerD3D9.h
@@ -0,0 +1,34 @@
+/* -*- 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 GFX_READBACKLAYERD3D9_H
+#define GFX_READBACKLAYERD3D9_H
+
+#include "LayerManagerD3D9.h"
+#include "ReadbackLayer.h"
+
+namespace mozilla {
+namespace layers {
+
+class ReadbackLayerD3D9 :
+ public ReadbackLayer,
+ public LayerD3D9
+{
+public:
+ ReadbackLayerD3D9(LayerManagerD3D9 *aManager)
+ : ReadbackLayer(aManager, nullptr),
+ LayerD3D9(aManager)
+ {
+ mImplData = static_cast<LayerD3D9*>(this);
+ }
+
+ virtual Layer* GetLayer() { return this; }
+ virtual void RenderLayer() {}
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif /* GFX_READBACKLAYERD3D9_H */
diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp
new file mode 100644
index 000000000..9828450d1
--- /dev/null
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -0,0 +1,1218 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/. */
+
+#include "TextureD3D9.h"
+#include "CompositorD3D9.h"
+#include "gfxContext.h"
+#include "gfxImageSurface.h"
+#include "Effects.h"
+#include "gfxWindowsPlatform.h"
+#include "gfx2DGlue.h"
+#include "gfxUtils.h"
+#include "mozilla/gfx/2D.h"
+#include "GeckoProfiler.h"
+
+using namespace mozilla::gfx;
+
+namespace mozilla {
+namespace layers {
+
+static uint32_t GetRequiredTilesD3D9(uint32_t aSize, uint32_t aMaxSize)
+{
+ uint32_t requiredTiles = aSize / aMaxSize;
+ if (aSize % aMaxSize) {
+ requiredTiles++;
+ }
+ return requiredTiles;
+}
+
+TextureSourceD3D9::~TextureSourceD3D9()
+{
+ MOZ_ASSERT(!mCreatingDeviceManager ||
+ mCreatingDeviceManager->IsInTextureHostList(this),
+ "Inconsistency in list of texture hosts.");
+ // Remove ourselves from the list of d3d9 texture hosts.
+ if (mPreviousHost) {
+ MOZ_ASSERT(mPreviousHost->mNextHost == this);
+ mPreviousHost->mNextHost = mNextHost;
+ } else if (mCreatingDeviceManager) {
+ mCreatingDeviceManager->RemoveTextureListHead(this);
+ }
+ if (mNextHost) {
+ MOZ_ASSERT(mNextHost->mPreviousHost == this);
+ mNextHost->mPreviousHost = mPreviousHost;
+ }
+}
+
+already_AddRefed<TextureHost>
+CreateTextureHostD3D9(const SurfaceDescriptor& aDesc,
+ ISurfaceAllocator* aDeallocator,
+ TextureFlags aFlags)
+{
+ RefPtr<TextureHost> result;
+ switch (aDesc.type()) {
+ case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
+ result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
+ break;
+ }
+ case SurfaceDescriptor::TSurfaceDescriptorD3D9: {
+ result = new TextureHostD3D9(aFlags, aDesc);
+ break;
+ }
+ case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
+ result = new DXGITextureHostD3D9(aFlags, aDesc);
+ break;
+ }
+ case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr: {
+ result = new DXGIYCbCrTextureHostD3D9(aFlags, aDesc.get_SurfaceDescriptorDXGIYCbCr());
+ break;
+ }
+ default: {
+ NS_WARNING("Unsupported SurfaceDescriptor type");
+ }
+ }
+ return result.forget();
+}
+
+static SurfaceFormat
+D3D9FormatToSurfaceFormat(_D3DFORMAT format)
+{
+ switch (format) {
+ case D3DFMT_X8R8G8B8:
+ return SurfaceFormat::B8G8R8X8;
+ case D3DFMT_A8R8G8B8:
+ return SurfaceFormat::B8G8R8A8;
+ case D3DFMT_A8:
+ return SurfaceFormat::A8;
+ default:
+ NS_ERROR("Bad texture format");
+ }
+ return SurfaceFormat::UNKNOWN;
+}
+
+static _D3DFORMAT
+SurfaceFormatToD3D9Format(SurfaceFormat format)
+{
+ switch (format) {
+ case SurfaceFormat::B8G8R8X8:
+ return D3DFMT_X8R8G8B8;
+ case SurfaceFormat::B8G8R8A8:
+ return D3DFMT_A8R8G8B8;
+ case SurfaceFormat::A8:
+ return D3DFMT_A8;
+ default:
+ NS_ERROR("Bad texture format");
+ }
+ return D3DFMT_A8R8G8B8;
+}
+
+CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture,
+ SurfaceInitMode aInit,
+ const gfx::IntRect& aRect)
+ : CompositingRenderTarget(aRect.TopLeft())
+ , mInitMode(aInit)
+{
+ MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
+ MOZ_ASSERT(aTexture);
+
+ mTexture = aTexture;
+ mTexture->GetSurfaceLevel(0, getter_AddRefs(mSurface));
+ NS_ASSERTION(mSurface, "Couldn't create surface for texture");
+ TextureSourceD3D9::SetSize(aRect.Size());
+
+ if (aInit == INIT_MODE_CLEAR) {
+ ClearOnBind();
+ }
+}
+
+CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface,
+ SurfaceInitMode aInit,
+ const gfx::IntRect& aRect)
+ : CompositingRenderTarget(aRect.TopLeft())
+ , mSurface(aSurface)
+ , mInitMode(aInit)
+{
+ MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
+ MOZ_ASSERT(mSurface);
+ TextureSourceD3D9::SetSize(aRect.Size());
+
+ if (aInit == INIT_MODE_CLEAR) {
+ ClearOnBind();
+ }
+}
+
+CompositingRenderTargetD3D9::~CompositingRenderTargetD3D9()
+{
+ MOZ_COUNT_DTOR(CompositingRenderTargetD3D9);
+}
+
+void
+CompositingRenderTargetD3D9::BindRenderTarget(IDirect3DDevice9* aDevice)
+{
+ aDevice->SetRenderTarget(0, mSurface);
+ if (mClearOnBind) {
+ aDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
+ mClearOnBind = false;
+ }
+}
+
+IntSize
+CompositingRenderTargetD3D9::GetSize() const
+{
+ return TextureSourceD3D9::GetSize();
+}
+
+/**
+ * Helper method for DataToTexture.
+ * The last three params are out params.
+ * Returns the created texture, or null if we fail.
+ */
+already_AddRefed<IDirect3DTexture9>
+TextureSourceD3D9::InitTextures(DeviceManagerD3D9* aDeviceManager,
+ const IntSize &aSize,
+ _D3DFORMAT aFormat,
+ RefPtr<IDirect3DSurface9>& aSurface,
+ D3DLOCKED_RECT& aLockedRect)
+{
+ if (!aDeviceManager) {
+ return nullptr;
+ }
+ RefPtr<IDirect3DTexture9> result;
+ // D3D9Ex doesn't support managed textures and we don't want the hassle even
+ // if we don't have Ex. We could use dynamic textures
+ // here but since Images are immutable that probably isn't such a great
+ // idea.
+ result = aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_DEFAULT, this);
+ if (!result) {
+ return nullptr;
+ }
+
+ RefPtr<IDirect3DTexture9> tmpTexture =
+ aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_SYSTEMMEM, this);
+ if (!tmpTexture) {
+ return nullptr;
+ }
+
+ tmpTexture->GetSurfaceLevel(0, getter_AddRefs(aSurface));
+
+ HRESULT hr = aSurface->LockRect(&aLockedRect, nullptr, 0);
+ if (FAILED(hr) || !aLockedRect.pBits) {
+ gfxCriticalError() << "Failed to lock rect initialize texture in D3D9 " << hexa(hr);
+ return nullptr;
+ }
+
+ return result.forget();
+}
+
+/**
+ * Helper method for DataToTexture.
+ */
+static void
+FinishTextures(DeviceManagerD3D9* aDeviceManager,
+ IDirect3DTexture9* aTexture,
+ IDirect3DSurface9* aSurface)
+{
+ if (!aDeviceManager) {
+ return;
+ }
+
+ aSurface->UnlockRect();
+ RefPtr<IDirect3DSurface9> dstSurface;
+ aTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+ aDeviceManager->device()->UpdateSurface(aSurface, nullptr, dstSurface,
+ nullptr);
+}
+
+already_AddRefed<IDirect3DTexture9>
+TextureSourceD3D9::DataToTexture(DeviceManagerD3D9* aDeviceManager,
+ unsigned char *aData,
+ int aStride,
+ const IntSize &aSize,
+ _D3DFORMAT aFormat,
+ uint32_t aBPP)
+{
+ PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
+ RefPtr<IDirect3DSurface9> surface;
+ D3DLOCKED_RECT lockedRect;
+ RefPtr<IDirect3DTexture9> texture = InitTextures(aDeviceManager, aSize, aFormat,
+ surface, lockedRect);
+ if (!texture) {
+ return nullptr;
+ }
+
+ uint32_t width = aSize.width * aBPP;
+
+ for (int y = 0; y < aSize.height; y++) {
+ memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
+ aData + aStride * y,
+ width);
+ }
+
+ FinishTextures(aDeviceManager, texture, surface);
+
+ return texture.forget();
+}
+
+already_AddRefed<IDirect3DTexture9>
+TextureSourceD3D9::TextureToTexture(DeviceManagerD3D9* aDeviceManager,
+ IDirect3DTexture9* aTexture,
+ const IntSize& aSize,
+ _D3DFORMAT aFormat)
+{
+ if (!aDeviceManager) {
+ return nullptr;
+ }
+
+ RefPtr<IDirect3DTexture9> texture =
+ aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_DEFAULT, this);
+ if (!texture) {
+ return nullptr;
+ }
+
+ HRESULT hr = aDeviceManager->device()->UpdateTexture(aTexture, texture);
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ return texture.forget();
+}
+
+DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
+ CompositorD3D9* aCompositor,
+ TextureFlags aFlags,
+ StereoMode aStereoMode)
+ : mCompositor(aCompositor)
+ , mFormat(aFormat)
+ , mCurrentTile(0)
+ , mFlags(aFlags)
+ , mIsTiled(false)
+ , mIterating(false)
+ , mAllowTextureUploads(true)
+{
+ mStereoMode = aStereoMode;
+ MOZ_COUNT_CTOR(DataTextureSourceD3D9);
+}
+
+DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
+ gfx::IntSize aSize,
+ CompositorD3D9* aCompositor,
+ IDirect3DTexture9* aTexture,
+ TextureFlags aFlags)
+ : mCompositor(aCompositor)
+ , mFormat(aFormat)
+ , mCurrentTile(0)
+ , mFlags(aFlags)
+ , mIsTiled(false)
+ , mIterating(false)
+ , mAllowTextureUploads(false)
+{
+ mSize = aSize;
+ mTexture = aTexture;
+ mStereoMode = StereoMode::MONO;
+ MOZ_COUNT_CTOR(DataTextureSourceD3D9);
+}
+
+DataTextureSourceD3D9::~DataTextureSourceD3D9()
+{
+ MOZ_COUNT_DTOR(DataTextureSourceD3D9);
+}
+
+IDirect3DTexture9*
+DataTextureSourceD3D9::GetD3D9Texture()
+{
+ return mIterating ? mTileTextures[mCurrentTile]
+ : mTexture;
+}
+
+bool
+DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface,
+ nsIntRegion* aDestRegion,
+ gfx::IntPoint* aSrcOffset)
+{
+ PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
+ // Right now we only support full surface update. If aDestRegion is provided,
+ // It will be ignored. Incremental update with a source offset is only used
+ // on Mac so it is not clear that we ever will need to support it for D3D.
+ MOZ_ASSERT(!aSrcOffset);
+
+ MOZ_ASSERT(mAllowTextureUploads);
+ if (!mAllowTextureUploads) {
+ return false;
+ }
+
+ if (!mCompositor || !mCompositor->device()) {
+ NS_WARNING("No D3D device to update the texture.");
+ return false;
+ }
+
+ uint32_t bpp = BytesPerPixel(aSurface->GetFormat());
+ RefPtr<DeviceManagerD3D9> deviceManager = DeviceManagerD3D9::Get();
+
+ mSize = aSurface->GetSize();
+ mFormat = aSurface->GetFormat();
+
+ _D3DFORMAT format = D3DFMT_A8R8G8B8;
+ switch (mFormat) {
+ case SurfaceFormat::B8G8R8X8:
+ format = D3DFMT_X8R8G8B8;
+ bpp = 4;
+ break;
+ case SurfaceFormat::B8G8R8A8:
+ format = D3DFMT_A8R8G8B8;
+ bpp = 4;
+ break;
+ case SurfaceFormat::A8:
+ format = D3DFMT_A8;
+ bpp = 1;
+ break;
+ default:
+ NS_WARNING("Bad image format");
+ return false;
+ }
+
+ int32_t maxSize = mCompositor->GetMaxTextureSize();
+ if ((mSize.width <= maxSize && mSize.height <= maxSize) ||
+ (mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
+ mIsTiled = false;
+
+ if (mTexture) {
+ D3DSURFACE_DESC currentDesc;
+ mTexture->GetLevelDesc(0, &currentDesc);
+
+ // Make sure there's no size mismatch, if there is, recreate.
+ if (currentDesc.Width != mSize.width || currentDesc.Height != mSize.height ||
+ currentDesc.Format != format) {
+ mTexture = nullptr;
+ // Make sure we upload the whole surface.
+ aDestRegion = nullptr;
+ }
+ }
+
+ if (!mTexture) {
+ // TODO Improve: Reallocating this texture is costly enough
+ // that it causes us to skip frames on scrolling
+ // important pages like Facebook.
+ mTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_DEFAULT, this);
+ mIsTiled = false;
+ if (!mTexture) {
+ Reset();
+ return false;
+ }
+
+ if (mFlags & TextureFlags::COMPONENT_ALPHA) {
+ aDestRegion = nullptr;
+ }
+ }
+
+ DataSourceSurface::MappedSurface map;
+ if (!aSurface->Map(DataSourceSurface::MapType::READ, &map)) {
+ gfxCriticalError() << "Failed to map surface.";
+ Reset();
+ return false;
+ }
+
+ nsIntRegion regionToUpdate = aDestRegion ? *aDestRegion : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height));
+
+ RefPtr<IDirect3DTexture9> srcTexture;
+ RefPtr<IDirect3DSurface9> srcSurface;
+
+ if (mFormat == SurfaceFormat::A8) {
+ // A8 doesn't appear to work with CreateOffscreenPlainSurface
+ srcTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_SYSTEMMEM, this);
+ if (!srcTexture) {
+ aSurface->Unmap();
+ return false;
+ }
+ srcTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
+ } else {
+ HRESULT hr = mCompositor->device()->CreateOffscreenPlainSurface(mSize.width, mSize.height, format, D3DPOOL_SYSTEMMEM, getter_AddRefs(srcSurface), nullptr);
+ if (FAILED(hr)) {
+ aSurface->Unmap();
+ return false;
+ }
+ }
+
+ RefPtr<IDirect3DSurface9> destSurface;
+ mTexture->GetSurfaceLevel(0, getter_AddRefs(destSurface));
+
+ D3DLOCKED_RECT rect;
+ HRESULT hr = srcSurface->LockRect(&rect, nullptr, 0);
+ if (FAILED(hr) || !rect.pBits) {
+ gfxCriticalError() << "Failed to lock rect initialize texture in D3D9 " << hexa(hr);
+ return false;
+ }
+
+ for (auto iter = regionToUpdate.RectIter(); !iter.Done(); iter.Next()) {
+ const nsIntRect& iterRect = iter.Get();
+ uint8_t* src = map.mData + map.mStride * iterRect.y + BytesPerPixel(aSurface->GetFormat()) * iterRect.x;
+ uint8_t* dest = reinterpret_cast<uint8_t*>(rect.pBits) + rect.Pitch * iterRect.y + BytesPerPixel(aSurface->GetFormat()) * iterRect.x;
+
+ for (int y = 0; y < iterRect.height; y++) {
+ memcpy(dest + rect.Pitch * y,
+ src + map.mStride * y,
+ iterRect.width * bpp);
+ }
+ }
+
+ srcSurface->UnlockRect();
+ aSurface->Unmap();
+
+ for (auto iter = regionToUpdate.RectIter(); !iter.Done(); iter.Next()) {
+ const nsIntRect& iterRect = iter.Get();
+
+ RECT updateRect;
+ updateRect.left = iterRect.x;
+ updateRect.top = iterRect.y;
+ updateRect.right = iterRect.XMost();
+ updateRect.bottom = iterRect.YMost();
+ POINT point = { updateRect.left, updateRect.top };
+
+ mCompositor->device()->UpdateSurface(srcSurface, &updateRect, destSurface, &point);
+ }
+ } else {
+ mIsTiled = true;
+ uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) *
+ GetRequiredTilesD3D9(mSize.height, maxSize);
+ mTileTextures.resize(tileCount);
+ mTexture = nullptr;
+
+ for (uint32_t i = 0; i < tileCount; i++) {
+ IntRect tileRect = GetTileRect(i);
+ unsigned char* data = aSurface->GetData() +
+ tileRect.y * aSurface->Stride() +
+ tileRect.x * bpp;
+ mTileTextures[i] = DataToTexture(deviceManager,
+ data,
+ aSurface->Stride(),
+ IntSize(tileRect.width, tileRect.height),
+ format,
+ bpp);
+ if (!mTileTextures[i]) {
+ NS_WARNING("Could not upload texture");
+ Reset();
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static CompositorD3D9* AssertD3D9Compositor(Compositor* aCompositor)
+{
+ CompositorD3D9* compositor = aCompositor ? aCompositor->AsCompositorD3D9()
+ : nullptr;
+ if (!compositor) {
+ // We probably had a device reset and this D3D9 texture was already sent but
+ // we are now falling back to a basic compositor. That can happen if a video
+ // is playing while the device reset occurs and it's not too bad if we miss a
+ // few frames.
+ gfxCriticalNote << "[D3D9] Attempt to set an incompatible compositor";
+ }
+ return compositor;
+}
+
+void
+DataTextureSourceD3D9::SetCompositor(Compositor* aCompositor)
+{
+ CompositorD3D9* d3dCompositor = AssertD3D9Compositor(aCompositor);
+ if (!d3dCompositor) {
+ Reset();
+ return;
+ }
+ if (mCompositor && mCompositor != d3dCompositor) {
+ Reset();
+ }
+ mCompositor = d3dCompositor;
+}
+
+void
+DataTextureSourceD3D9::Reset()
+{
+ mSize.width = 0;
+ mSize.height = 0;
+ mIsTiled = false;
+ mTexture = nullptr;
+ mTileTextures.clear();
+}
+
+IntRect
+DataTextureSourceD3D9::GetTileRect(uint32_t aTileIndex) const
+{
+ uint32_t maxSize = mCompositor->GetMaxTextureSize();
+ uint32_t horizontalTiles = GetRequiredTilesD3D9(mSize.width, maxSize);
+ uint32_t verticalTiles = GetRequiredTilesD3D9(mSize.height, maxSize);
+
+ uint32_t verticalTile = aTileIndex / horizontalTiles;
+ uint32_t horizontalTile = aTileIndex % horizontalTiles;
+
+ return IntRect(horizontalTile * maxSize,
+ verticalTile * maxSize,
+ horizontalTile < (horizontalTiles - 1) ? maxSize : mSize.width % maxSize,
+ verticalTile < (verticalTiles - 1) ? maxSize : mSize.height % maxSize);
+}
+
+IntRect
+DataTextureSourceD3D9::GetTileRect()
+{
+ return GetTileRect(mCurrentTile);
+}
+
+
+D3D9TextureData::D3D9TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+ IDirect3DTexture9* aTexture)
+: mTexture(aTexture)
+, mSize(aSize)
+, mFormat(aFormat)
+, mNeedsClear(false)
+, mNeedsClearWhite(false)
+{
+ MOZ_COUNT_CTOR(D3D9TextureData);
+}
+
+D3D9TextureData::~D3D9TextureData()
+{
+ MOZ_COUNT_DTOR(D3D9TextureData);
+}
+
+D3D9TextureData*
+D3D9TextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+ TextureAllocationFlags aAllocFlags)
+{
+ _D3DFORMAT format = SurfaceFormatToD3D9Format(aFormat);
+ RefPtr<DeviceManagerD3D9> deviceManager = DeviceManagerD3D9::Get();
+ RefPtr<IDirect3DTexture9> d3d9Texture = deviceManager ? deviceManager->CreateTexture(aSize, format,
+ D3DPOOL_SYSTEMMEM,
+ nullptr)
+ : nullptr;
+ if (!d3d9Texture) {
+ NS_WARNING("Could not create a d3d9 texture");
+ return nullptr;
+ }
+ D3D9TextureData* data = new D3D9TextureData(aSize, aFormat, d3d9Texture);
+
+ data->mNeedsClear = aAllocFlags & ALLOC_CLEAR_BUFFER;
+ data->mNeedsClearWhite = aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE;
+
+ return data;
+}
+
+TextureData*
+D3D9TextureData::CreateSimilar(LayersIPCChannel*, LayersBackend, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const
+{
+ return D3D9TextureData::Create(mSize, mFormat, aAllocFlags);
+}
+
+void
+D3D9TextureData::FillInfo(TextureData::Info& aInfo) const
+{
+ aInfo.size = mSize;
+ aInfo.format = mFormat;
+ aInfo.hasIntermediateBuffer = true;
+ aInfo.supportsMoz2D = true;
+ aInfo.canExposeMappedData = false;
+ aInfo.hasSynchronization = false;
+}
+
+bool
+D3D9TextureData::Lock(OpenMode aMode)
+{
+ if (!DeviceManagerD3D9::GetDevice()) {
+ // If the device has failed then we should not lock the surface,
+ // even if we could.
+ mD3D9Surface = nullptr;
+ return false;
+ }
+
+ if (!mD3D9Surface) {
+ HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mD3D9Surface));
+ if (FAILED(hr)) {
+ NS_WARNING("Failed to get texture surface level.");
+ return false;
+ }
+ }
+ return true;
+}
+void
+D3D9TextureData::Unlock()
+{
+ if (mLockRect) {
+ mD3D9Surface->UnlockRect();
+ mLockRect = false;
+ }
+}
+
+bool
+D3D9TextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
+{
+ mTexture->AddRef(); // Release in TextureHostD3D9::TextureHostD3D9
+ aOutDescriptor = SurfaceDescriptorD3D9(reinterpret_cast<uintptr_t>(mTexture.get()));
+ return true;
+}
+
+already_AddRefed<gfx::DrawTarget>
+D3D9TextureData::BorrowDrawTarget()
+{
+ MOZ_ASSERT(mD3D9Surface);
+ if (!mD3D9Surface) {
+ return nullptr;
+ }
+
+ RefPtr<DrawTarget> dt;
+ if (ContentForFormat(mFormat) == gfxContentType::COLOR) {
+ RefPtr<gfxASurface> surface = new gfxWindowsSurface(mD3D9Surface);
+ if (!surface || surface->CairoStatus()) {
+ NS_WARNING("Could not create gfxASurface for d3d9 surface");
+ return nullptr;
+ }
+ dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, mSize);
+
+ if (!dt) {
+ return nullptr;
+ }
+ } else {
+ // gfxWindowsSurface don't support transparency so we can't use the d3d9
+ // windows surface optimization.
+ // Instead we have to use a gfxImageSurface and fallback for font drawing.
+ D3DLOCKED_RECT rect;
+ HRESULT hr = mD3D9Surface->LockRect(&rect, nullptr, 0);
+ if (FAILED(hr) || !rect.pBits) {
+ gfxCriticalError() << "Failed to lock rect borrowing the target in D3D9 (BDT) " << hexa(hr);
+ return nullptr;
+ }
+ dt = gfxPlatform::CreateDrawTargetForData((uint8_t*)rect.pBits, mSize,
+ rect.Pitch, mFormat);
+ if (!dt) {
+ return nullptr;
+ }
+
+ mLockRect = true;
+ }
+
+ if (mNeedsClear) {
+ dt->ClearRect(Rect(0, 0, mSize.width, mSize.height));
+ mNeedsClear = false;
+ }
+ if (mNeedsClearWhite) {
+ dt->FillRect(Rect(0, 0, mSize.width, mSize.height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
+ mNeedsClearWhite = false;
+ }
+
+ return dt.forget();
+}
+
+bool
+D3D9TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
+{
+ MOZ_ASSERT(mD3D9Surface);
+
+ // gfxWindowsSurface don't support transparency so we can't use the d3d9
+ // windows surface optimization.
+ // Instead we have to use a gfxImageSurface and fallback for font drawing.
+ D3DLOCKED_RECT rect;
+ HRESULT hr = mD3D9Surface->LockRect(&rect, nullptr, 0);
+ if (FAILED(hr) || !rect.pBits) {
+ gfxCriticalError() << "Failed to lock rect borrowing the target in D3D9 (UFS) " << hexa(hr);
+ return false;
+ }
+
+ RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
+
+ if (!srcSurf) {
+ gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (D3D9).";
+ mD3D9Surface->UnlockRect();
+ return false;
+ }
+
+ DataSourceSurface::MappedSurface sourceMap;
+ if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
+ gfxCriticalError() << "Failed to map source surface for UpdateFromSurface (D3D9).";
+ return false;
+ }
+
+ for (int y = 0; y < srcSurf->GetSize().height; y++) {
+ memcpy((uint8_t*)rect.pBits + rect.Pitch * y,
+ sourceMap.mData + sourceMap.mStride * y,
+ srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
+ }
+
+ srcSurf->Unmap();
+ mD3D9Surface->UnlockRect();
+
+ return true;
+}
+
+DXGID3D9TextureData::DXGID3D9TextureData(gfx::SurfaceFormat aFormat,
+ IDirect3DTexture9* aTexture, HANDLE aHandle,
+ IDirect3DDevice9* aDevice)
+: mDevice(aDevice)
+, mTexture(aTexture)
+, mFormat(aFormat)
+, mHandle(aHandle)
+{
+ MOZ_COUNT_CTOR(DXGID3D9TextureData);
+}
+
+DXGID3D9TextureData::~DXGID3D9TextureData()
+{
+ gfxWindowsPlatform::sD3D9SharedTextures -= mDesc.Width * mDesc.Height * 4;
+ MOZ_COUNT_DTOR(DXGID3D9TextureData);
+}
+
+// static
+DXGID3D9TextureData*
+DXGID3D9TextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+ TextureFlags aFlags,
+ IDirect3DDevice9* aDevice)
+{
+ PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
+ MOZ_ASSERT(aFormat == gfx::SurfaceFormat::B8G8R8A8);
+ if (aFormat != gfx::SurfaceFormat::B8G8R8A8) {
+ return nullptr;
+ }
+
+ RefPtr<IDirect3DTexture9> texture;
+ HANDLE shareHandle = nullptr;
+ HRESULT hr = aDevice->CreateTexture(aSize.width, aSize.height,
+ 1,
+ D3DUSAGE_RENDERTARGET,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_DEFAULT,
+ getter_AddRefs(texture),
+ &shareHandle);
+ if (FAILED(hr) || !shareHandle) {
+ return nullptr;
+ }
+
+ D3DSURFACE_DESC surfaceDesc;
+ hr = texture->GetLevelDesc(0, &surfaceDesc);
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+ DXGID3D9TextureData* data = new DXGID3D9TextureData(aFormat, texture, shareHandle, aDevice);
+ data->mDesc = surfaceDesc;
+
+ gfxWindowsPlatform::sD3D9SharedTextures += aSize.width * aSize.height * 4;
+ return data;
+}
+
+void
+DXGID3D9TextureData::FillInfo(TextureData::Info& aInfo) const
+{
+ aInfo.size = GetSize();
+ aInfo.format = mFormat;
+ aInfo.supportsMoz2D = false;
+ aInfo.canExposeMappedData = false;
+ aInfo.hasIntermediateBuffer = false;
+ aInfo.hasSynchronization = false;
+}
+
+already_AddRefed<IDirect3DSurface9>
+DXGID3D9TextureData::GetD3D9Surface() const
+{
+ RefPtr<IDirect3DSurface9> textureSurface;
+ HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(textureSurface));
+ NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+
+ return textureSurface.forget();
+}
+
+bool
+DXGID3D9TextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
+{
+ aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)(mHandle), mFormat, GetSize());
+ return true;
+}
+
+
+TextureHostD3D9::TextureHostD3D9(TextureFlags aFlags,
+ const SurfaceDescriptorD3D9& aDescriptor)
+ : TextureHost(aFlags)
+ , mFormat(SurfaceFormat::UNKNOWN)
+ , mIsLocked(false)
+{
+ mTexture = reinterpret_cast<IDirect3DTexture9*>(aDescriptor.texture());
+ MOZ_ASSERT(mTexture);
+ mTexture->Release(); // see AddRef in TextureClientD3D9::ToSurfaceDescriptor
+ MOZ_ASSERT(mTexture);
+ D3DSURFACE_DESC desc;
+ HRESULT hr = mTexture->GetLevelDesc(0, &desc);
+ if (!FAILED(hr)) {
+ mFormat = D3D9FormatToSurfaceFormat(desc.Format);
+ mSize.width = desc.Width;
+ mSize.height = desc.Height;
+ }
+}
+
+bool
+DataTextureSourceD3D9::UpdateFromTexture(IDirect3DTexture9* aTexture,
+ const nsIntRegion* aRegion)
+{
+ PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
+ MOZ_ASSERT(aTexture);
+
+ D3DSURFACE_DESC desc;
+ HRESULT hr = aTexture->GetLevelDesc(0, &desc);
+ if (FAILED(hr)) {
+ return false;
+ } else {
+ // If we changed the compositor, the size might have been reset to zero
+ // Otherwise the texture size must not change.
+ MOZ_ASSERT(mFormat == D3D9FormatToSurfaceFormat(desc.Format));
+ MOZ_ASSERT(!mSize.width || mSize.width == desc.Width);
+ MOZ_ASSERT(!mSize.height || mSize.height == desc.Height);
+ mSize = IntSize(desc.Width, desc.Height);
+ }
+
+ RefPtr<DeviceManagerD3D9> dm = DeviceManagerD3D9::Get();
+ if (!dm || !dm->device()) {
+ return false;
+ }
+
+ if (!mTexture) {
+ mTexture = dm->CreateTexture(mSize, SurfaceFormatToD3D9Format(mFormat),
+ D3DPOOL_DEFAULT, this);
+ if (!mTexture) {
+ NS_WARNING("Failed to create a texture");
+ return false;
+ }
+ }
+
+ RefPtr<IDirect3DSurface9> srcSurface;
+ RefPtr<IDirect3DSurface9> dstSurface;
+
+ hr = aTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
+ if (FAILED(hr)) {
+ return false;
+ }
+ hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ if (aRegion) {
+ for (auto iter = aRegion->RectIter(); !iter.Done(); iter.Next()) {
+ const IntRect& iterRect = iter.Get();
+ RECT rect;
+ rect.left = iterRect.x;
+ rect.top = iterRect.y;
+ rect.right = iterRect.XMost();
+ rect.bottom = iterRect.YMost();
+
+ POINT point;
+ point.x = iterRect.x;
+ point.y = iterRect.y;
+ hr = dm->device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
+ if (FAILED(hr)) {
+ NS_WARNING("Failed Update the surface");
+ return false;
+ }
+ }
+ } else {
+ hr = dm->device()->UpdateSurface(srcSurface, nullptr, dstSurface, nullptr);
+ if (FAILED(hr)) {
+ NS_WARNING("Failed Update the surface");
+ return false;
+ }
+ }
+ mIsTiled = false;
+ return true;
+}
+
+void
+TextureHostD3D9::UpdatedInternal(const nsIntRegion* aRegion)
+{
+ MOZ_ASSERT(mTexture);
+ if (!mTexture) {
+ return;
+ }
+
+ const nsIntRegion* regionToUpdate = aRegion;
+ if (!mTextureSource) {
+ mTextureSource = new DataTextureSourceD3D9(mFormat, mSize, mCompositor,
+ nullptr, mFlags);
+ if (mFlags & TextureFlags::COMPONENT_ALPHA) {
+ // Update the full region the first time for component alpha textures.
+ regionToUpdate = nullptr;
+ }
+ }
+
+ if (!mTextureSource->UpdateFromTexture(mTexture, regionToUpdate)) {
+ gfxCriticalNote << "[D3D9] DataTextureSourceD3D9::UpdateFromTexture failed";
+ }
+
+ ReadUnlock();
+}
+
+IDirect3DDevice9*
+TextureHostD3D9::GetDevice()
+{
+ if (mFlags & TextureFlags::INVALID_COMPOSITOR) {
+ return nullptr;
+ }
+ return mCompositor ? mCompositor->device() : nullptr;
+}
+
+void
+TextureHostD3D9::SetCompositor(Compositor* aCompositor)
+{
+ mCompositor = AssertD3D9Compositor(aCompositor);
+ if (!mCompositor) {
+ mTextureSource = nullptr;
+ return;
+ }
+ if (mTextureSource) {
+ mTextureSource->SetCompositor(aCompositor);
+ }
+}
+
+Compositor*
+TextureHostD3D9::GetCompositor()
+{
+ return mCompositor;
+}
+
+bool
+TextureHostD3D9::BindTextureSource(CompositableTextureSourceRef& aTexture)
+{
+ MOZ_ASSERT(mIsLocked);
+ MOZ_ASSERT(mTextureSource);
+ aTexture = mTextureSource;
+ return !!aTexture;
+}
+
+bool
+TextureHostD3D9::Lock()
+{
+ MOZ_ASSERT(!mIsLocked);
+ // XXX - Currently if a TextureHostD3D9 is created but Update is never called,
+ // it will not have a TextureSource although it could since it has a valid
+ // D3D9 texture.
+ mIsLocked = !!mTextureSource;
+ return mIsLocked;
+}
+
+void
+TextureHostD3D9::Unlock()
+{
+ MOZ_ASSERT(mIsLocked);
+ mIsLocked = false;
+}
+
+void
+TextureHostD3D9::DeallocateDeviceData()
+{
+ mTextureSource = nullptr;
+}
+
+DXGITextureHostD3D9::DXGITextureHostD3D9(TextureFlags aFlags,
+ const SurfaceDescriptorD3D10& aDescriptor)
+ : TextureHost(aFlags)
+ , mHandle(aDescriptor.handle())
+ , mFormat(aDescriptor.format())
+ , mSize(aDescriptor.size())
+ , mIsLocked(false)
+{
+ MOZ_ASSERT(mHandle);
+ OpenSharedHandle();
+}
+
+IDirect3DDevice9*
+DXGITextureHostD3D9::GetDevice()
+{
+ if (mFlags & TextureFlags::INVALID_COMPOSITOR) {
+ return nullptr;
+ }
+ return mCompositor ? mCompositor->device() : nullptr;
+}
+
+void
+DXGITextureHostD3D9::OpenSharedHandle()
+{
+ MOZ_ASSERT(!mTextureSource);
+
+ if (!GetDevice()) {
+ return;
+ }
+
+ RefPtr<IDirect3DTexture9> texture;
+ HRESULT hr = GetDevice()->CreateTexture(mSize.width, mSize.height, 1,
+ D3DUSAGE_RENDERTARGET,
+ SurfaceFormatToD3D9Format(mFormat),
+ D3DPOOL_DEFAULT,
+ getter_AddRefs(texture),
+ (HANDLE*)&mHandle);
+ if (FAILED(hr)) {
+ NS_WARNING("Failed to open shared texture");
+ return;
+ }
+
+ mTextureSource = new DataTextureSourceD3D9(mFormat, mSize, mCompositor, texture);
+
+ return;
+}
+
+bool
+DXGITextureHostD3D9::BindTextureSource(CompositableTextureSourceRef& aTexture)
+{
+ MOZ_ASSERT(mIsLocked);
+ MOZ_ASSERT(mTextureSource);
+ aTexture = mTextureSource;
+ return !!aTexture;
+}
+
+bool
+DXGITextureHostD3D9::Lock()
+{
+ MOZ_ASSERT(!mIsLocked);
+
+ if (!mCompositor) {
+ NS_WARNING("no suitable compositor");
+ return false;
+ }
+
+ if (!GetDevice()) {
+ return false;
+ }
+
+ if (!mTextureSource) {
+ OpenSharedHandle();
+ }
+ mIsLocked = !!mTextureSource;
+ return mIsLocked;
+}
+
+void
+DXGITextureHostD3D9::Unlock()
+{
+ MOZ_ASSERT(mIsLocked);
+ mIsLocked = false;
+}
+
+void
+DXGITextureHostD3D9::SetCompositor(Compositor* aCompositor)
+{
+ mCompositor = AssertD3D9Compositor(aCompositor);
+ if (!mCompositor) {
+ mTextureSource = nullptr;
+ }
+}
+
+Compositor*
+DXGITextureHostD3D9::GetCompositor()
+{
+ return mCompositor;
+}
+
+void
+DXGITextureHostD3D9::DeallocateDeviceData()
+{
+ mTextureSource = nullptr;
+}
+
+DXGIYCbCrTextureHostD3D9::DXGIYCbCrTextureHostD3D9(TextureFlags aFlags,
+ const SurfaceDescriptorDXGIYCbCr& aDescriptor)
+ : TextureHost(aFlags)
+ , mSize(aDescriptor.size())
+ , mSizeY(aDescriptor.sizeY())
+ , mSizeCbCr(aDescriptor.sizeCbCr())
+ , mIsLocked(false)
+{
+ mHandles[0] = reinterpret_cast<HANDLE>(aDescriptor.handleY());
+ mHandles[1] = reinterpret_cast<HANDLE>(aDescriptor.handleCb());
+ mHandles[2] = reinterpret_cast<HANDLE>(aDescriptor.handleCr());
+}
+
+IDirect3DDevice9*
+DXGIYCbCrTextureHostD3D9::GetDevice()
+{
+ if (mFlags & TextureFlags::INVALID_COMPOSITOR) {
+ return nullptr;
+ }
+ return mCompositor ? mCompositor->device() : nullptr;
+}
+
+void
+DXGIYCbCrTextureHostD3D9::SetCompositor(Compositor* aCompositor)
+{
+ mCompositor = AssertD3D9Compositor(aCompositor);
+ if (!mCompositor) {
+ mTextureSources[0] = nullptr;
+ mTextureSources[1] = nullptr;
+ mTextureSources[2] = nullptr;
+ }
+}
+
+Compositor*
+DXGIYCbCrTextureHostD3D9::GetCompositor()
+{
+ return mCompositor;
+}
+
+bool
+DXGIYCbCrTextureHostD3D9::Lock()
+{
+ if (!mCompositor) {
+ NS_WARNING("no suitable compositor");
+ return false;
+ }
+
+ if (!GetDevice()) {
+ NS_WARNING("trying to lock a TextureHost without a D3D device");
+ return false;
+ }
+ if (!mTextureSources[0]) {
+ if (!mHandles[0]) {
+ return false;
+ }
+
+ if (FAILED(GetDevice()->CreateTexture(mSizeY.width, mSizeY.height,
+ 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT,
+ getter_AddRefs(mTextures[0]), &mHandles[0]))) {
+ return false;
+ }
+
+ if (FAILED(GetDevice()->CreateTexture(mSizeCbCr.width, mSizeCbCr.height,
+ 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT,
+ getter_AddRefs(mTextures[1]), &mHandles[1]))) {
+ return false;
+ }
+
+ if (FAILED(GetDevice()->CreateTexture(mSizeCbCr.width, mSizeCbCr.height,
+ 1, 0, D3DFMT_A8, D3DPOOL_DEFAULT,
+ getter_AddRefs(mTextures[2]), &mHandles[2]))) {
+ return false;
+ }
+
+ mTextureSources[0] = new DataTextureSourceD3D9(SurfaceFormat::A8, mSize, mCompositor, mTextures[0]);
+ mTextureSources[1] = new DataTextureSourceD3D9(SurfaceFormat::A8, mSize, mCompositor, mTextures[1]);
+ mTextureSources[2] = new DataTextureSourceD3D9(SurfaceFormat::A8, mSize, mCompositor, mTextures[2]);
+ mTextureSources[0]->SetNextSibling(mTextureSources[1]);
+ mTextureSources[1]->SetNextSibling(mTextureSources[2]);
+ }
+
+ mIsLocked = true;
+ return mIsLocked;
+}
+
+void
+DXGIYCbCrTextureHostD3D9::Unlock()
+{
+ MOZ_ASSERT(mIsLocked);
+ mIsLocked = false;
+}
+
+bool
+DXGIYCbCrTextureHostD3D9::BindTextureSource(CompositableTextureSourceRef& aTexture)
+{
+ MOZ_ASSERT(mIsLocked);
+ // If Lock was successful we must have a valid TextureSource.
+ MOZ_ASSERT(mTextureSources[0] && mTextureSources[1] && mTextureSources[2]);
+ aTexture = mTextureSources[0].get();
+ return !!aTexture;
+}
+
+}
+}
diff --git a/gfx/layers/d3d9/TextureD3D9.h b/gfx/layers/d3d9/TextureD3D9.h
new file mode 100644
index 000000000..67d7a13a6
--- /dev/null
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -0,0 +1,433 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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_TEXTURED3D9_H
+#define MOZILLA_GFX_TEXTURED3D9_H
+
+#include "mozilla/layers/Compositor.h"
+#include "mozilla/layers/TextureClient.h"
+#include "mozilla/layers/TextureHost.h"
+#include "mozilla/GfxMessageUtils.h"
+#include "mozilla/gfx/2D.h"
+#include "gfxWindowsPlatform.h"
+#include "d3d9.h"
+#include <vector>
+#include "DeviceManagerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+class CompositorD3D9;
+
+class TextureSourceD3D9
+{
+ friend class DeviceManagerD3D9;
+
+public:
+ TextureSourceD3D9()
+ : mPreviousHost(nullptr)
+ , mNextHost(nullptr)
+ , mCreatingDeviceManager(nullptr)
+ {}
+ virtual ~TextureSourceD3D9();
+
+ virtual IDirect3DTexture9* GetD3D9Texture() { return mTexture; }
+
+ StereoMode GetStereoMode() const { return mStereoMode; };
+
+ // Release all texture memory resources held by the texture host.
+ virtual void ReleaseTextureResources()
+ {
+ mTexture = nullptr;
+ }
+
+protected:
+ virtual gfx::IntSize GetSize() const { return mSize; }
+ void SetSize(const gfx::IntSize& aSize) { mSize = aSize; }
+
+ // Helper methods for creating and copying textures.
+ already_AddRefed<IDirect3DTexture9> InitTextures(
+ DeviceManagerD3D9* aDeviceManager,
+ const gfx::IntSize &aSize,
+ _D3DFORMAT aFormat,
+ RefPtr<IDirect3DSurface9>& aSurface,
+ D3DLOCKED_RECT& aLockedRect);
+
+ already_AddRefed<IDirect3DTexture9> DataToTexture(
+ DeviceManagerD3D9* aDeviceManager,
+ unsigned char *aData,
+ int aStride,
+ const gfx::IntSize &aSize,
+ _D3DFORMAT aFormat,
+ uint32_t aBPP);
+
+ // aTexture should be in SYSTEMMEM, returns a texture in the default
+ // pool (that is, in video memory).
+ already_AddRefed<IDirect3DTexture9> TextureToTexture(
+ DeviceManagerD3D9* aDeviceManager,
+ IDirect3DTexture9* aTexture,
+ const gfx::IntSize& aSize,
+ _D3DFORMAT aFormat);
+
+ gfx::IntSize mSize;
+
+ // Linked list of all objects holding d3d9 textures.
+ TextureSourceD3D9* mPreviousHost;
+ TextureSourceD3D9* mNextHost;
+ // The device manager that created our textures.
+ RefPtr<DeviceManagerD3D9> mCreatingDeviceManager;
+
+ StereoMode mStereoMode;
+ RefPtr<IDirect3DTexture9> mTexture;
+};
+
+/**
+ * A TextureSource that implements the DataTextureSource interface.
+ * it can be used without a TextureHost and is able to upload texture data
+ * from a gfx::DataSourceSurface.
+ */
+class DataTextureSourceD3D9 : public DataTextureSource
+ , public TextureSourceD3D9
+ , public BigImageIterator
+{
+public:
+ /// Constructor allowing the texture to perform texture uploads.
+ ///
+ /// The texture can be used as an actual DataTextureSource.
+ DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
+ CompositorD3D9* aCompositor,
+ TextureFlags aFlags = TextureFlags::DEFAULT,
+ StereoMode aStereoMode = StereoMode::MONO);
+
+ /// Constructor for textures created around DXGI shared handles, disallowing
+ /// texture uploads.
+ ///
+ /// The texture CANNOT be used as a DataTextureSource.
+ DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
+ gfx::IntSize aSize,
+ CompositorD3D9* aCompositor,
+ IDirect3DTexture9* aTexture,
+ TextureFlags aFlags = TextureFlags::DEFAULT);
+
+ virtual ~DataTextureSourceD3D9();
+
+ virtual const char* Name() const override { return "DataTextureSourceD3D9"; }
+
+ // DataTextureSource
+
+ virtual bool Update(gfx::DataSourceSurface* aSurface,
+ nsIntRegion* aDestRegion = nullptr,
+ gfx::IntPoint* aSrcOffset = nullptr) override;
+
+ // TextureSource
+
+ virtual TextureSourceD3D9* AsSourceD3D9() override { return this; }
+
+ virtual IDirect3DTexture9* GetD3D9Texture() override;
+
+ // Returns nullptr if this texture was created by a DXGI TextureHost.
+ virtual DataTextureSource* AsDataTextureSource() override { return mAllowTextureUploads ? this : nullptr; }
+
+ virtual void DeallocateDeviceData() override { mTexture = nullptr; }
+
+ virtual gfx::IntSize GetSize() const override { return mSize; }
+
+ virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
+
+ virtual void SetCompositor(Compositor* aCompositor) override;
+
+ // BigImageIterator
+
+ virtual BigImageIterator* AsBigImageIterator() override { return mIsTiled ? this : nullptr; }
+
+ virtual size_t GetTileCount() override { return mTileTextures.size(); }
+
+ virtual bool NextTile() override { return (++mCurrentTile < mTileTextures.size()); }
+
+ virtual gfx::IntRect GetTileRect() override;
+
+ virtual void EndBigImageIteration() override { mIterating = false; }
+
+ virtual void BeginBigImageIteration() override
+ {
+ mIterating = true;
+ mCurrentTile = 0;
+ }
+
+ /**
+ * Copy the content of aTexture using the GPU.
+ */
+ bool UpdateFromTexture(IDirect3DTexture9* aTexture, const nsIntRegion* aRegion);
+
+protected:
+ gfx::IntRect GetTileRect(uint32_t aTileIndex) const;
+
+ void Reset();
+
+ std::vector< RefPtr<IDirect3DTexture9> > mTileTextures;
+ RefPtr<CompositorD3D9> mCompositor;
+ gfx::SurfaceFormat mFormat;
+ uint32_t mCurrentTile;
+ TextureFlags mFlags;
+ bool mIsTiled;
+ bool mIterating;
+ bool mAllowTextureUploads;
+};
+
+/**
+ * Needs a D3D9 context on the client side.
+ * The corresponding TextureHost is TextureHostD3D9.
+ */
+class D3D9TextureData : public TextureData
+{
+public:
+ ~D3D9TextureData();
+
+ virtual bool Serialize(SurfaceDescriptor& aOutDescrptor) override;
+
+ virtual bool Lock(OpenMode aMode) override;
+
+ virtual void Unlock() override;
+
+ virtual void FillInfo(TextureData::Info& aInfo) const override;
+
+ virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
+
+ virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
+
+ virtual TextureData*
+ CreateSimilar(LayersIPCChannel* aAllocator,
+ LayersBackend aLayersBackend,
+ TextureFlags aFlags,
+ TextureAllocationFlags aAllocFlags) const override;
+
+ static D3D9TextureData*
+ Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags);
+
+ virtual void Deallocate(LayersIPCChannel* aAllocator) override {}
+
+protected:
+ D3D9TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+ IDirect3DTexture9* aTexture);
+
+ RefPtr<IDirect3DTexture9> mTexture;
+ RefPtr<IDirect3DSurface9> mD3D9Surface;
+ gfx::IntSize mSize;
+ gfx::SurfaceFormat mFormat;
+ bool mNeedsClear;
+ bool mNeedsClearWhite;
+ bool mLockRect;
+};
+
+/**
+ * Wraps a D3D9 texture, shared with the compositor though DXGI.
+ * At the moment it is only used with D3D11 compositing, and the corresponding
+ * TextureHost is DXGITextureHostD3D11.
+ */
+class DXGID3D9TextureData : public TextureData
+{
+public:
+ static DXGID3D9TextureData*
+ Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureFlags aFlags, IDirect3DDevice9* aDevice);
+
+ ~DXGID3D9TextureData();
+
+ virtual void FillInfo(TextureData::Info& aInfo) const override;
+
+ virtual bool Lock(OpenMode) override { return true; }
+
+ virtual void Unlock() override {}
+
+ virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
+
+ virtual void Deallocate(LayersIPCChannel* aAllocator) override {}
+
+ IDirect3DDevice9* GetD3D9Device() { return mDevice; }
+ IDirect3DTexture9* GetD3D9Texture() { return mTexture; }
+ HANDLE GetShareHandle() const { return mHandle; }
+ already_AddRefed<IDirect3DSurface9> GetD3D9Surface() const;
+
+ const D3DSURFACE_DESC& GetDesc() const
+ {
+ return mDesc;
+ }
+
+ gfx::IntSize GetSize() const { return gfx::IntSize(mDesc.Width, mDesc.Height); }
+
+protected:
+ DXGID3D9TextureData(gfx::SurfaceFormat aFormat,
+ IDirect3DTexture9* aTexture, HANDLE aHandle,
+ IDirect3DDevice9* aDevice);
+
+ RefPtr<IDirect3DDevice9> mDevice;
+ RefPtr<IDirect3DTexture9> mTexture;
+ gfx::SurfaceFormat mFormat;
+ HANDLE mHandle;
+ D3DSURFACE_DESC mDesc;
+};
+
+class TextureHostD3D9 : public TextureHost
+{
+public:
+ TextureHostD3D9(TextureFlags aFlags,
+ const SurfaceDescriptorD3D9& aDescriptor);
+
+ virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override;
+
+ virtual void DeallocateDeviceData() override;
+
+ virtual void SetCompositor(Compositor* aCompositor) override;
+
+ virtual Compositor* GetCompositor() override;
+
+ virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
+
+ virtual bool Lock() override;
+
+ virtual void Unlock() override;
+
+ virtual gfx::IntSize GetSize() const override { return mSize; }
+
+ virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
+ {
+ return nullptr;
+ }
+
+ virtual bool HasIntermediateBuffer() const override { return true; }
+
+protected:
+ TextureHostD3D9(TextureFlags aFlags);
+ IDirect3DDevice9* GetDevice();
+
+ virtual void UpdatedInternal(const nsIntRegion* aRegion) override;
+
+ RefPtr<DataTextureSourceD3D9> mTextureSource;
+ RefPtr<IDirect3DTexture9> mTexture;
+ RefPtr<CompositorD3D9> mCompositor;
+ gfx::IntSize mSize;
+ gfx::SurfaceFormat mFormat;
+ bool mIsLocked;
+};
+
+class DXGITextureHostD3D9 : public TextureHost
+{
+public:
+ DXGITextureHostD3D9(TextureFlags aFlags,
+ const SurfaceDescriptorD3D10& aDescriptor);
+
+ virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override;
+
+ virtual void DeallocateDeviceData() override;
+
+ virtual void SetCompositor(Compositor* aCompositor) override;
+
+ virtual Compositor* GetCompositor() override;
+
+ virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
+
+ virtual gfx::IntSize GetSize() const override { return mSize; }
+
+ virtual bool Lock() override;
+
+ virtual void Unlock() override;
+
+ virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
+ {
+ return nullptr; // TODO: cf bug 872568
+ }
+
+protected:
+ void OpenSharedHandle();
+ IDirect3DDevice9* GetDevice();
+
+ RefPtr<DataTextureSourceD3D9> mTextureSource;
+ RefPtr<CompositorD3D9> mCompositor;
+ WindowsHandle mHandle;
+ gfx::SurfaceFormat mFormat;
+ gfx::IntSize mSize;
+ bool mIsLocked;
+};
+
+class DXGIYCbCrTextureHostD3D9 : public TextureHost
+{
+public:
+ DXGIYCbCrTextureHostD3D9(TextureFlags aFlags,
+ const SurfaceDescriptorDXGIYCbCr& aDescriptor);
+
+ virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override;
+
+ virtual void DeallocateDeviceData() override {}
+
+ virtual void SetCompositor(Compositor* aCompositor) override;
+
+ virtual Compositor* GetCompositor() override;
+
+ virtual gfx::SurfaceFormat GetFormat() const override { return gfx::SurfaceFormat::YUV; }
+
+ // Bug 1305906 fixes YUVColorSpace handling
+ virtual YUVColorSpace GetYUVColorSpace() const override { return YUVColorSpace::BT601; }
+
+ virtual bool Lock() override;
+ virtual void Unlock() override;
+ virtual gfx::IntSize GetSize() const override { return mSize; }
+
+ virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
+ {
+ return nullptr;
+ }
+
+ protected:
+ IDirect3DDevice9* GetDevice();
+
+ HANDLE mHandles[3];
+ RefPtr<IDirect3DTexture9> mTextures[3];
+ RefPtr<DataTextureSourceD3D9> mTextureSources[3];
+
+ RefPtr<CompositorD3D9> mCompositor;
+ gfx::IntSize mSize;
+ gfx::IntSize mSizeY;
+ gfx::IntSize mSizeCbCr;
+ bool mIsLocked;
+ };
+
+class CompositingRenderTargetD3D9 : public CompositingRenderTarget,
+ public TextureSourceD3D9
+{
+public:
+ CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture,
+ SurfaceInitMode aInit,
+ const gfx::IntRect& aRect);
+ // use for rendering to the main window, cannot be rendered as a texture
+ CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface,
+ SurfaceInitMode aInit,
+ const gfx::IntRect& aRect);
+ virtual ~CompositingRenderTargetD3D9();
+
+ virtual const char* Name() const override { return "CompositingRenderTargetD3D9"; }
+
+ virtual TextureSourceD3D9* AsSourceD3D9() override
+ {
+ MOZ_ASSERT(mTexture,
+ "No texture, can't be indirectly rendered. Is this the screen backbuffer?");
+ return this;
+ }
+
+ virtual gfx::IntSize GetSize() const override;
+
+ void BindRenderTarget(IDirect3DDevice9* aDevice);
+
+ IDirect3DSurface9* GetD3D9Surface() const { return mSurface; }
+
+private:
+ friend class CompositorD3D9;
+
+ RefPtr<IDirect3DSurface9> mSurface;
+ SurfaceInitMode mInitMode;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_TEXTURED3D9_H */
diff --git a/gfx/layers/d3d9/genshaders.sh b/gfx/layers/d3d9/genshaders.sh
new file mode 100644
index 000000000..f85762450
--- /dev/null
+++ b/gfx/layers/d3d9/genshaders.sh
@@ -0,0 +1,35 @@
+# 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/.
+
+tempfile=tmpShaderHeader
+rm LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -ELayerQuadVS -nologo -Fh$tempfile -VnLayerQuadVS
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -ERGBAShader -nologo -Tps_2_0 -Fh$tempfile -VnRGBAShaderPS
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -EComponentPass1Shader -nologo -Tps_2_0 -Fh$tempfile -VnComponentPass1ShaderPS
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -EComponentPass2Shader -nologo -Tps_2_0 -Fh$tempfile -VnComponentPass2ShaderPS
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -ERGBShader -nologo -Tps_2_0 -Fh$tempfile -VnRGBShaderPS
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -EYCbCrShader -nologo -Tps_2_0 -Fh$tempfile -VnYCbCrShaderPS
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -ESolidColorShader -nologo -Tps_2_0 -Fh$tempfile -VnSolidColorShaderPS
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -ELayerQuadVSMask -nologo -Fh$tempfile -VnLayerQuadVSMask
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -ERGBAShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnRGBAShaderPSMask
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -EComponentPass1ShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnComponentPass1ShaderPSMask
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -EComponentPass2ShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnComponentPass2ShaderPSMask
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -ERGBShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnRGBShaderPSMask
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -EYCbCrShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnYCbCrShaderPSMask
+cat $tempfile >> LayerManagerD3D9Shaders.h
+fxc LayerManagerD3D9Shaders.hlsl -ESolidColorShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnSolidColorShaderPSMask
+cat $tempfile >> LayerManagerD3D9Shaders.h
+rm $tempfile