DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (dcc6d7a0dc00)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
/* -*- 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(PCompositorParent* aParent, nsIWidget *aWidget);
  ~CompositorD3D9();

  virtual bool Initialize() override;
  virtual void Destroy() 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);
  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::Rect &aClipRect,
                        const EffectChain &aEffectChain,
                        gfx::Float aOpacity,
                        const gfx::Matrix4x4& aTransform,
                        const gfx::Rect& aVisibleRect) override;

  virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
                          const gfx::Rect *aClipRectIn,
                          const gfx::Rect& aRenderBounds,
                          gfx::Rect *aClipRectOut = nullptr,
                          gfx::Rect *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; }

#ifdef MOZ_DUMP_PAINTING
  virtual const char* Name() const override { return "Direct3D9"; }
#endif

  virtual LayersBackend GetBackendType() const override {
    return LayersBackend::LAYERS_D3D9;
  }

  virtual nsIWidget* GetWidget() const override { return mWidget; }

  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 SetSamplerForFilter(gfx::Filter aFilter);
  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();

  /**
   * 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);

  virtual gfx::IntSize GetWidgetSize() const override
  {
    return mSize;
  }

  /* Device manager instance for this compositor */
  RefPtr<DeviceManagerD3D9> mDeviceManager;

  /* Swap chain associated with this compositor */
  RefPtr<SwapChainD3D9> mSwapChain;

  /* Widget associated with this layer manager */
  nsIWidget *mWidget;

  RefPtr<CompositingRenderTargetD3D9> mDefaultRT;
  RefPtr<CompositingRenderTargetD3D9> mCurrentRT;

  gfx::IntSize mSize;

  uint32_t mDeviceResetCount;
  uint32_t mFailedResetAttempts;
};

}
}

#endif