gfx/layers/d3d9/CompositorD3D9.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "CompositorD3D9.h"
     7 #include "LayerManagerD3D9Shaders.h"
     8 #include "gfxWindowsPlatform.h"
     9 #include "nsIWidget.h"
    10 #include "mozilla/layers/ImageHost.h"
    11 #include "mozilla/layers/ContentHost.h"
    12 #include "mozilla/layers/Effects.h"
    13 #include "nsWindowsHelpers.h"
    14 #include "Nv3DVUtils.h"
    15 #include "gfxFailure.h"
    16 #include "mozilla/layers/PCompositorParent.h"
    17 #include "mozilla/layers/LayerManagerComposite.h"
    18 #include "gfxPrefs.h"
    20 using namespace mozilla::gfx;
    22 namespace mozilla {
    23 namespace layers {
    25 CompositorD3D9::CompositorD3D9(PCompositorParent* aParent, nsIWidget *aWidget)
    26   : Compositor(aParent)
    27   , mWidget(aWidget)
    28   , mDeviceResetCount(0)
    29 {
    30   Compositor::SetBackend(LayersBackend::LAYERS_D3D9);
    31 }
    33 CompositorD3D9::~CompositorD3D9()
    34 {
    35   mSwapChain = nullptr;
    36   mDeviceManager = nullptr;
    37 }
    39 bool
    40 CompositorD3D9::Initialize()
    41 {
    42   if (!gfxPlatform::CanUseDirect3D9()) {
    43     NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
    44     return false;
    45   }
    47   mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
    48   if (!mDeviceManager) {
    49     return false;
    50   }
    52   mSwapChain = mDeviceManager->
    53     CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
    55   if (!mSwapChain) {
    56     return false;
    57   }
    59   return true;
    60 }
    62 TextureFactoryIdentifier
    63 CompositorD3D9::GetTextureFactoryIdentifier()
    64 {
    65   TextureFactoryIdentifier ident;
    66   ident.mMaxTextureSize = GetMaxTextureSize();
    67   ident.mParentBackend = LayersBackend::LAYERS_D3D9;
    68   ident.mParentProcessId = XRE_GetProcessType();
    69   return ident;
    70 }
    72 bool
    73 CompositorD3D9::CanUseCanvasLayerForSize(const IntSize &aSize)
    74 {
    75   int32_t maxTextureSize = GetMaxTextureSize();
    77   if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) {
    78     return false;
    79   }
    81   return true;
    82 }
    84 int32_t
    85 CompositorD3D9::GetMaxTextureSize() const
    86 {
    87   return mDeviceManager ? mDeviceManager->GetMaxTextureSize() : INT32_MAX;
    88 }
    90 TemporaryRef<DataTextureSource>
    91 CompositorD3D9::CreateDataTextureSource(TextureFlags aFlags)
    92 {
    93   return new DataTextureSourceD3D9(SurfaceFormat::UNKNOWN, this, aFlags);
    94 }
    96 TemporaryRef<CompositingRenderTarget>
    97 CompositorD3D9::CreateRenderTarget(const gfx::IntRect &aRect,
    98                                    SurfaceInitMode aInit)
    99 {
   100   if (!mDeviceManager) {
   101     return nullptr;
   102   }
   104   RefPtr<IDirect3DTexture9> texture;
   105   HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
   106                                        D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
   107                                        D3DPOOL_DEFAULT, byRef(texture),
   108                                        nullptr);
   109   if (FAILED(hr)) {
   110     ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTarget: Failed to create texture"),
   111                   hr);
   112     return nullptr;
   113   }
   115   RefPtr<CompositingRenderTargetD3D9> rt =
   116     new CompositingRenderTargetD3D9(texture, aInit, aRect);
   118   return rt;
   119 }
   121 TemporaryRef<CompositingRenderTarget>
   122 CompositorD3D9::CreateRenderTargetFromSource(const gfx::IntRect &aRect,
   123                                              const CompositingRenderTarget *aSource,
   124                                              const gfx::IntPoint &aSourcePoint)
   125 {
   126   if (!mDeviceManager) {
   127     return nullptr;
   128   }
   130   RefPtr<IDirect3DTexture9> texture;
   131   HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
   132                                        D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
   133                                        D3DPOOL_DEFAULT, byRef(texture),
   134                                        nullptr);
   135   if (FAILED(hr)) {
   136     ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTargetFromSource: Failed to create texture"),
   137                   hr);
   138     return nullptr;
   139   }
   141   if (aSource) {
   142     nsRefPtr<IDirect3DSurface9> sourceSurface =
   143       static_cast<const CompositingRenderTargetD3D9*>(aSource)->GetD3D9Surface();
   145     nsRefPtr<IDirect3DSurface9> destSurface;
   146     hr = texture->GetSurfaceLevel(0, getter_AddRefs(destSurface));
   147     if (FAILED(hr)) {
   148       NS_WARNING("Failed to get texture surface level for dest.");
   149     }
   151     if (sourceSurface && destSurface) {
   152       RECT sourceRect;
   153       sourceRect.left = aSourcePoint.x;
   154       sourceRect.right = aSourcePoint.x + aRect.width;
   155       sourceRect.top = aSourcePoint.y;
   156       sourceRect.bottom = aSourcePoint.y + aRect.height;
   157       RECT destRect;
   158       destRect.left = 0;
   159       destRect.right = aRect.width;
   160       destRect.top = 0;
   161       destRect.bottom = aRect.height;
   163       // copy the source to the dest
   164       hr = device()->StretchRect(sourceSurface,
   165                                  &sourceRect,
   166                                  destSurface,
   167                                  &destRect,
   168                                  D3DTEXF_NONE);
   169       if (FAILED(hr)) {
   170         ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTargetFromSource: Failed to update texture"),
   171                       hr);
   172       }
   173     }
   174   }
   176   RefPtr<CompositingRenderTargetD3D9> rt =
   177     new CompositingRenderTargetD3D9(texture,
   178                                     INIT_MODE_NONE,
   179                                     aRect);
   181   return rt;
   182 }
   184 void
   185 CompositorD3D9::SetRenderTarget(CompositingRenderTarget *aRenderTarget)
   186 {
   187   MOZ_ASSERT(aRenderTarget && mDeviceManager);
   188   RefPtr<CompositingRenderTargetD3D9> oldRT = mCurrentRT;
   189   mCurrentRT = static_cast<CompositingRenderTargetD3D9*>(aRenderTarget);
   190   mCurrentRT->BindRenderTarget(device());
   191   PrepareViewport(mCurrentRT->GetSize(), Matrix());
   192 }
   194 static DeviceManagerD3D9::ShaderMode
   195 ShaderModeForEffectType(EffectTypes aEffectType, gfx::SurfaceFormat aFormat)
   196 {
   197   switch (aEffectType) {
   198   case EFFECT_SOLID_COLOR:
   199     return DeviceManagerD3D9::SOLIDCOLORLAYER;
   200   case EFFECT_RENDER_TARGET:
   201     return DeviceManagerD3D9::RGBALAYER;
   202   case EFFECT_RGB:
   203     if (aFormat == SurfaceFormat::B8G8R8A8 || aFormat == SurfaceFormat::R8G8B8A8)
   204       return DeviceManagerD3D9::RGBALAYER;
   205     return DeviceManagerD3D9::RGBLAYER;
   206   case EFFECT_YCBCR:
   207     return DeviceManagerD3D9::YCBCRLAYER;
   208   }
   210   MOZ_CRASH("Bad effect type");
   211 }
   213 void
   214 CompositorD3D9::ClearRect(const gfx::Rect& aRect)
   215 {
   216   D3DRECT rect;
   217   rect.x1 = aRect.X();
   218   rect.y1 = aRect.Y();
   219   rect.x2 = aRect.XMost();
   220   rect.y2 = aRect.YMost();
   222   device()->Clear(1, &rect, D3DCLEAR_TARGET,
   223                   0x00000000, 0, 0);
   224 }
   226 void
   227 CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
   228                          const gfx::Rect &aClipRect,
   229                          const EffectChain &aEffectChain,
   230                          gfx::Float aOpacity,
   231                          const gfx::Matrix4x4 &aTransform)
   232 {
   233   if (!mDeviceManager) {
   234     return;
   235   }
   237   IDirect3DDevice9* d3d9Device = device();
   238   MOZ_ASSERT(d3d9Device, "We should be able to get a device now");
   240   MOZ_ASSERT(mCurrentRT, "No render target");
   241   d3d9Device->SetVertexShaderConstantF(CBmLayerTransform, &aTransform._11, 4);
   243   IntPoint origin = mCurrentRT->GetOrigin();
   244   float renderTargetOffset[] = { origin.x, origin.y, 0, 0 };
   245   d3d9Device->SetVertexShaderConstantF(CBvRenderTargetOffset,
   246                                        renderTargetOffset,
   247                                        1);
   248   d3d9Device->SetVertexShaderConstantF(CBvLayerQuad,
   249                                        ShaderConstantRect(aRect.x,
   250                                                           aRect.y,
   251                                                           aRect.width,
   252                                                           aRect.height),
   253                                        1);
   254   bool target = false;
   256   if (aEffectChain.mPrimaryEffect->mType != EFFECT_SOLID_COLOR) {
   257     float opacity[4];
   258     /*
   259      * We always upload a 4 component float, but the shader will use only the
   260      * first component since it's declared as a 'float'.
   261      */
   262     opacity[0] = aOpacity;
   263     d3d9Device->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
   264   }
   266   bool isPremultiplied = true;
   268   MaskType maskType = MaskNone;
   270   if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
   271     if (aTransform.Is2D()) {
   272       maskType = Mask2d;
   273     } else {
   274       maskType = Mask3d;
   275     }
   276   }
   278   RECT scissor;
   279   scissor.left = aClipRect.x;
   280   scissor.right = aClipRect.XMost();
   281   scissor.top = aClipRect.y;
   282   scissor.bottom = aClipRect.YMost();
   283   d3d9Device->SetScissorRect(&scissor);
   285   uint32_t maskTexture = 0;
   286   switch (aEffectChain.mPrimaryEffect->mType) {
   287   case EFFECT_SOLID_COLOR:
   288     {
   289       // output color is premultiplied, so we need to adjust all channels.
   290       Color layerColor =
   291         static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
   292       float color[4];
   293       color[0] = layerColor.r * layerColor.a * aOpacity;
   294       color[1] = layerColor.g * layerColor.a * aOpacity;
   295       color[2] = layerColor.b * layerColor.a * aOpacity;
   296       color[3] = layerColor.a * aOpacity;
   298       d3d9Device->SetPixelShaderConstantF(CBvColor, color, 1);
   300       maskTexture = mDeviceManager
   301         ->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER, maskType);
   302     }
   303     break;
   304   case EFFECT_RENDER_TARGET:
   305   case EFFECT_RGB:
   306     {
   307       TexturedEffect* texturedEffect =
   308         static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
   310       Rect textureCoords = texturedEffect->mTextureCoords;
   311       d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
   312                                            ShaderConstantRect(
   313                                              textureCoords.x,
   314                                              textureCoords.y,
   315                                              textureCoords.width,
   316                                              textureCoords.height),
   317                                            1);
   319       SetSamplerForFilter(texturedEffect->mFilter);
   321       TextureSourceD3D9* source = texturedEffect->mTexture->AsSourceD3D9();
   322       d3d9Device->SetTexture(0, source->GetD3D9Texture());
   324       maskTexture = mDeviceManager
   325         ->SetShaderMode(ShaderModeForEffectType(aEffectChain.mPrimaryEffect->mType,
   326                                                 texturedEffect->mTexture->GetFormat()),
   327                         maskType);
   329       isPremultiplied = texturedEffect->mPremultiplied;
   330     }
   331     break;
   332   case EFFECT_YCBCR:
   333     {
   334       EffectYCbCr* ycbcrEffect =
   335         static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
   337       SetSamplerForFilter(Filter::LINEAR);
   339       Rect textureCoords = ycbcrEffect->mTextureCoords;
   340       d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
   341                                            ShaderConstantRect(
   342                                              textureCoords.x,
   343                                              textureCoords.y,
   344                                              textureCoords.width,
   345                                              textureCoords.height),
   346                                            1);
   348       const int Y = 0, Cb = 1, Cr = 2;
   349       TextureSource* source = ycbcrEffect->mTexture;
   351       if (!source) {
   352         NS_WARNING("No texture to composite");
   353         return;
   354       }
   356       if (!source->GetSubSource(Y) || !source->GetSubSource(Cb) || !source->GetSubSource(Cr)) {
   357         // This can happen if we failed to upload the textures, most likely
   358         // because of unsupported dimensions (we don't tile YCbCr textures).
   359         return;
   360       }
   362       TextureSourceD3D9* sourceY  = source->GetSubSource(Y)->AsSourceD3D9();
   363       TextureSourceD3D9* sourceCb = source->GetSubSource(Cb)->AsSourceD3D9();
   364       TextureSourceD3D9* sourceCr = source->GetSubSource(Cr)->AsSourceD3D9();
   367       MOZ_ASSERT(sourceY->GetD3D9Texture());
   368       MOZ_ASSERT(sourceCb->GetD3D9Texture());
   369       MOZ_ASSERT(sourceCr->GetD3D9Texture());
   371       /*
   372        * Send 3d control data and metadata
   373        */
   374       if (mDeviceManager->GetNv3DVUtils()) {
   375         Nv_Stereo_Mode mode;
   376         switch (source->AsSourceD3D9()->GetStereoMode()) {
   377         case StereoMode::LEFT_RIGHT:
   378           mode = NV_STEREO_MODE_LEFT_RIGHT;
   379           break;
   380         case StereoMode::RIGHT_LEFT:
   381           mode = NV_STEREO_MODE_RIGHT_LEFT;
   382           break;
   383         case StereoMode::BOTTOM_TOP:
   384           mode = NV_STEREO_MODE_BOTTOM_TOP;
   385           break;
   386         case StereoMode::TOP_BOTTOM:
   387           mode = NV_STEREO_MODE_TOP_BOTTOM;
   388           break;
   389         case StereoMode::MONO:
   390           mode = NV_STEREO_MODE_MONO;
   391           break;
   392         }
   394         // Send control data even in mono case so driver knows to leave stereo mode.
   395         mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
   397         if (source->AsSourceD3D9()->GetStereoMode() != StereoMode::MONO) {
   398           mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
   400           nsRefPtr<IDirect3DSurface9> renderTarget;
   401           d3d9Device->GetRenderTarget(0, getter_AddRefs(renderTarget));
   402           mDeviceManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)aRect.width,
   403                                                              (unsigned int)aRect.height,
   404                                                              (HANDLE)(sourceY->GetD3D9Texture()),
   405                                                              (HANDLE)(renderTarget));
   406         }
   407       }
   409       // Linear scaling is default here, adhering to mFilter is difficult since
   410       // presumably even with point filtering we'll still want chroma upsampling
   411       // to be linear. In the current approach we can't.
   412       device()->SetTexture(Y, sourceY->GetD3D9Texture());
   413       device()->SetTexture(Cb, sourceCb->GetD3D9Texture());
   414       device()->SetTexture(Cr, sourceCr->GetD3D9Texture());
   415       maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, maskType);
   416     }
   417     break;
   418   case EFFECT_COMPONENT_ALPHA:
   419     {
   420       MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
   421       EffectComponentAlpha* effectComponentAlpha =
   422         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
   423       TextureSourceD3D9* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D9();
   424       TextureSourceD3D9* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D9();
   426       Rect textureCoords = effectComponentAlpha->mTextureCoords;
   427       d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
   428                                            ShaderConstantRect(
   429                                              textureCoords.x,
   430                                              textureCoords.y,
   431                                              textureCoords.width,
   432                                              textureCoords.height),
   433                                            1);
   435       SetSamplerForFilter(effectComponentAlpha->mFilter);
   437       maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS1, maskType);
   438       SetMask(aEffectChain, maskTexture);
   439       d3d9Device->SetTexture(0, sourceOnBlack->GetD3D9Texture());
   440       d3d9Device->SetTexture(1, sourceOnWhite->GetD3D9Texture());
   441       d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
   442       d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
   443       d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
   445       maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS2, maskType);
   446       SetMask(aEffectChain, maskTexture);
   447       d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
   448       d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
   449       d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
   451       // Restore defaults
   452       d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
   453       d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
   454       d3d9Device->SetTexture(1, nullptr);
   455     }
   456     return;
   457   default:
   458     NS_WARNING("Unknown shader type");
   459     return;
   460   }
   462   SetMask(aEffectChain, maskTexture);
   464   if (!isPremultiplied) {
   465     d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
   466   }
   468   HRESULT hr = d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
   470   if (!isPremultiplied) {
   471     d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
   472   }
   473 }
   475 void
   476 CompositorD3D9::SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture)
   477 {
   478   EffectMask *maskEffect =
   479     static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
   480   if (!maskEffect) {
   481     return;
   482   }
   484   TextureSourceD3D9 *source = maskEffect->mMaskTexture->AsSourceD3D9();
   486   MOZ_ASSERT(aMaskTexture >= 0);
   487   device()->SetTexture(aMaskTexture, source->GetD3D9Texture());
   489   const gfx::Matrix4x4& maskTransform = maskEffect->mMaskTransform;
   490   NS_ASSERTION(maskTransform.Is2D(), "How did we end up with a 3D transform here?!");
   491   Rect bounds = Rect(Point(), Size(maskEffect->mSize));
   492   bounds = maskTransform.As2D().TransformBounds(bounds);
   494   device()->SetVertexShaderConstantF(DeviceManagerD3D9::sMaskQuadRegister, 
   495                                      ShaderConstantRect(bounds.x,
   496                                                         bounds.y,
   497                                                         bounds.width,
   498                                                         bounds.height),
   499                                      1);
   500 }
   502 /**
   503  * In the next few methods we call |mParent->SendInvalidateAll()| - that has
   504  * a few uses - if our device or swap chain is not ready, it causes us to try
   505  * to render again, that means we keep trying to get a good device and swap
   506  * chain and don't block the main thread (which we would if we kept trying in
   507  * a busy loop because this is likely to happen in a sync transaction).
   508  * If we had to recreate our device, then we have new textures and we
   509  * need to reupload everything (not just what is currently invalid) from the
   510  * client side. That means we need to invalidate everything on the client.
   511  * If we just reset and didn't need to recreate, then we don't need to reupload
   512  * our textures, but we do need to redraw the whole window, which means we still
   513  * need to invalidate everything.
   514  * Currently we probably do this complete invalidation too much. But it is better
   515  * to do that than to miss an invalidation which would result in a black layer
   516  * (or multiple layers) until the user moves the mouse. The unnecessary invalidtion
   517  * only happens when the device is reset, so that should be pretty rare and when
   518  * other things are happening so the user does not expect super performance.
   519  */
   521 bool
   522 CompositorD3D9::EnsureSwapChain()
   523 {
   524   MOZ_ASSERT(mDeviceManager, "Don't call EnsureSwapChain without a device manager");
   526   if (!mSwapChain) {
   527     mSwapChain = mDeviceManager->
   528       CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
   529     // We could not create a swap chain, return false
   530     if (!mSwapChain) {
   531       // Check the state of the device too
   532       DeviceManagerState state = mDeviceManager->VerifyReadyForRendering();
   533       if (state == DeviceMustRecreate) {
   534         mDeviceManager = nullptr;
   535       }
   536       mParent->SendInvalidateAll();
   537       return false;
   538     }
   539   }
   541   // We have a swap chain, lets initialise it
   542   DeviceManagerState state = mSwapChain->PrepareForRendering();
   543   if (state == DeviceOK) {
   544     return true;
   545   }
   546   // Swap chain could not be initialised, handle the failure
   547   if (state == DeviceMustRecreate) {
   548     mDeviceManager = nullptr;
   549     mSwapChain = nullptr;
   550   }
   551   mParent->SendInvalidateAll();
   552   return false;
   553 }
   555 void
   556 CompositorD3D9::CheckResetCount()
   557 {
   558   if (mDeviceResetCount != mDeviceManager->GetDeviceResetCount()) {
   559     mParent->SendInvalidateAll();
   560   }
   561   mDeviceResetCount = mDeviceManager->GetDeviceResetCount();
   562 }
   564 bool
   565 CompositorD3D9::Ready()
   566 {
   567   if (mDeviceManager) {
   568     if (EnsureSwapChain()) {
   569       // We don't need to call VerifyReadyForRendering because that is
   570       // called by mSwapChain->PrepareForRendering() via EnsureSwapChain().
   572       CheckResetCount();
   573       return true;
   574     }
   575     return false;
   576   }
   578   NS_ASSERTION(!mCurrentRT && !mDefaultRT,
   579                "Shouldn't have any render targets around, they must be released before our device");
   580   mSwapChain = nullptr;
   582   mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
   583   if (!mDeviceManager) {
   584     mParent->SendInvalidateAll();
   585     return false;
   586   }
   587   if (EnsureSwapChain()) {
   588     CheckResetCount();
   589     return true;
   590   }
   591   return false;
   592 }
   594 static void
   595 CancelCompositing(Rect* aRenderBoundsOut)
   596 {
   597   if (aRenderBoundsOut) {
   598     *aRenderBoundsOut = Rect(0, 0, 0, 0);
   599   }
   600 }
   602 void
   603 CompositorD3D9::BeginFrame(const nsIntRegion& aInvalidRegion,
   604                            const Rect *aClipRectIn,
   605                            const gfx::Matrix& aTransform,
   606                            const Rect& aRenderBounds,
   607                            Rect *aClipRectOut,
   608                            Rect *aRenderBoundsOut)
   609 {
   610   MOZ_ASSERT(mDeviceManager && mSwapChain);
   612   mDeviceManager->SetupRenderState();
   614   EnsureSize();
   616   device()->Clear(0, nullptr, D3DCLEAR_TARGET, 0x00000000, 0, 0);
   617   device()->BeginScene();
   619   if (aClipRectOut) {
   620     *aClipRectOut = Rect(0, 0, mSize.width, mSize.height);
   621   }
   622   if (aRenderBoundsOut) {
   623     *aRenderBoundsOut = Rect(0, 0, mSize.width, mSize.height);
   624   }
   626   RECT r;
   627   if (aClipRectIn) {
   628     r.left = (LONG)aClipRectIn->x;
   629     r.top = (LONG)aClipRectIn->y;
   630     r.right = (LONG)(aClipRectIn->x + aClipRectIn->width);
   631     r.bottom = (LONG)(aClipRectIn->y + aClipRectIn->height);
   632   } else {
   633     r.left = r.top = 0;
   634     r.right = mSize.width;
   635     r.bottom = mSize.height;
   636   }
   637   device()->SetScissorRect(&r);
   639   nsRefPtr<IDirect3DSurface9> backBuffer = mSwapChain->GetBackBuffer();
   640   mDefaultRT = new CompositingRenderTargetD3D9(backBuffer,
   641                                                INIT_MODE_CLEAR,
   642                                                IntRect(0, 0, mSize.width, mSize.height));
   643   SetRenderTarget(mDefaultRT);
   644 }
   646 void
   647 CompositorD3D9::EndFrame()
   648 {
   649   if (mDeviceManager) {
   650     device()->EndScene();
   652     nsIntSize oldSize = mSize;
   653     EnsureSize();
   654     if (oldSize == mSize) {
   655       if (mTarget) {
   656         PaintToTarget();
   657       } else {
   658         mSwapChain->Present();
   659       }
   660     }
   661   }
   663   mCurrentRT = nullptr;
   664   mDefaultRT = nullptr;
   665 }
   667 void
   668 CompositorD3D9::PrepareViewport(const gfx::IntSize& aSize,
   669                                 const Matrix &aWorldTransform)
   670 {
   671   Matrix4x4 viewMatrix;
   672   /*
   673    * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
   674    * <1.0, -1.0> bottomright)
   675    */
   676   viewMatrix._11 = 2.0f / aSize.width;
   677   viewMatrix._22 = -2.0f / aSize.height;
   678   viewMatrix._41 = -1.0f;
   679   viewMatrix._42 = 1.0f;
   681   viewMatrix = Matrix4x4::From2D(aWorldTransform) * viewMatrix;
   683   HRESULT hr = device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
   685   if (FAILED(hr)) {
   686     NS_WARNING("Failed to set projection matrix");
   687   }
   688 }
   690 void
   691 CompositorD3D9::EnsureSize()
   692 {
   693   nsIntRect rect;
   694   mWidget->GetClientBounds(rect);
   696   mSize = rect.Size();
   697 }
   699 void
   700 CompositorD3D9::SetSamplerForFilter(Filter aFilter)
   701 {
   702   switch (aFilter) {
   703   case Filter::LINEAR:
   704     device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
   705     device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
   706     return;
   707   case Filter::POINT:
   708     device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
   709     device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
   710     return;
   711   default:
   712     device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
   713     device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
   714   }
   715 }
   717 void
   718 CompositorD3D9::PaintToTarget()
   719 {
   720   if (!mDeviceManager) {
   721     return;
   722   }
   724   nsRefPtr<IDirect3DSurface9> backBuff;
   725   nsRefPtr<IDirect3DSurface9> destSurf;
   726   device()->GetRenderTarget(0, getter_AddRefs(backBuff));
   728   D3DSURFACE_DESC desc;
   729   backBuff->GetDesc(&desc);
   731   device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
   732                                         D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
   733                                         getter_AddRefs(destSurf), nullptr);
   735   device()->GetRenderTargetData(backBuff, destSurf);
   737   D3DLOCKED_RECT rect;
   738   destSurf->LockRect(&rect, nullptr, D3DLOCK_READONLY);
   739   RefPtr<DataSourceSurface> sourceSurface =
   740     Factory::CreateWrappingDataSourceSurface((uint8_t*)rect.pBits,
   741                                              rect.Pitch,
   742                                              IntSize(desc.Width, desc.Height),
   743                                              SurfaceFormat::B8G8R8A8);
   744   mTarget->CopySurface(sourceSurface,
   745                        IntRect(0, 0, desc.Width, desc.Height),
   746                        IntPoint());
   747   mTarget->Flush();
   748   destSurf->UnlockRect();
   749 }
   751 void
   752 CompositorD3D9::ReportFailure(const nsACString &aMsg, HRESULT aCode)
   753 {
   754   // We could choose to abort here when hr == E_OUTOFMEMORY.
   755   nsCString msg;
   756   msg.Append(aMsg);
   757   msg.AppendLiteral(" Error code: ");
   758   msg.AppendInt(uint32_t(aCode));
   759   NS_WARNING(msg.BeginReading());
   761   gfx::LogFailure(msg);
   762 }
   764 }
   765 }

mercurial