diff options
Diffstat (limited to 'gfx/layers/d3d9')
-rw-r--r-- | gfx/layers/d3d9/CompositorD3D9.cpp | 1045 | ||||
-rw-r--r-- | gfx/layers/d3d9/CompositorD3D9.h | 189 | ||||
-rw-r--r-- | gfx/layers/d3d9/DeviceManagerD3D9.cpp | 966 | ||||
-rw-r--r-- | gfx/layers/d3d9/DeviceManagerD3D9.h | 353 | ||||
-rwxr-xr-x | gfx/layers/d3d9/LayerManagerD3D9Shaders.h | 1631 | ||||
-rw-r--r-- | gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl | 242 | ||||
-rw-r--r-- | gfx/layers/d3d9/Nv3DVUtils.cpp | 148 | ||||
-rw-r--r-- | gfx/layers/d3d9/Nv3DVUtils.h | 86 | ||||
-rw-r--r-- | gfx/layers/d3d9/ReadbackLayerD3D9.h | 34 | ||||
-rw-r--r-- | gfx/layers/d3d9/TextureD3D9.cpp | 1218 | ||||
-rw-r--r-- | gfx/layers/d3d9/TextureD3D9.h | 433 | ||||
-rw-r--r-- | gfx/layers/d3d9/genshaders.sh | 35 |
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(¶meters))) + 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, ¤tDesc); + + // 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 |