summaryrefslogtreecommitdiff
path: root/gfx/layers/d3d9/CompositorD3D9.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/d3d9/CompositorD3D9.cpp')
-rw-r--r--gfx/layers/d3d9/CompositorD3D9.cpp1001
1 files changed, 0 insertions, 1001 deletions
diff --git a/gfx/layers/d3d9/CompositorD3D9.cpp b/gfx/layers/d3d9/CompositorD3D9.cpp
deleted file mode 100644
index 6f01e7d152..0000000000
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ /dev/null
@@ -1,1001 +0,0 @@
-/* -*- 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 "gfxFailure.h"
-#include "mozilla/layers/LayerManagerComposite.h"
-#include "gfxPrefs.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)
-{
- 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;
- }
-
- 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());
-
- // 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);
- }
-}
-
-}
-}