Bug 1323791 - Part 5: Add generalized DrawGeometry() method and use it with DrawQuad() and DrawTriangles() r=bas
authorMiko Mynttinen <mikokm@gmail.com>
Mon, 20 Feb 2017 12:19:28 +0100
changeset 494354 5bf82944a61738b8ae61f3693fa72d4c6367e821
parent 494353 88dd8c893e26601e45bc0da7bb88cc9ab596d483
child 494355 c9f09b670a27bd01d89193b0d4c79f72001e7987
push id48023
push userjwwang@mozilla.com
push dateTue, 07 Mar 2017 02:32:15 +0000
reviewersbas
bugs1323791
milestone54.0a1
Bug 1323791 - Part 5: Add generalized DrawGeometry() method and use it with DrawQuad() and DrawTriangles() r=bas MozReview-Commit-ID: SKuxDDhdEE
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d11/CompositorD3D11.h
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -42,25 +42,33 @@ namespace layers {
 
 static bool CanUsePartialPresents(ID3D11Device* aDevice);
 
 struct Vertex
 {
     float position[2];
 };
 
+struct TexturedVertex
+{
+    float position[2];
+    float texCoords[2];
+};
+
 // {1E4D7BEB-D8EC-4A0B-BF0A-63E6DE129425}
 static const GUID sDeviceAttachmentsD3D11 =
 { 0x1e4d7beb, 0xd8ec, 0x4a0b, { 0xbf, 0xa, 0x63, 0xe6, 0xde, 0x12, 0x94, 0x25 } };
 // {88041664-C835-4AA8-ACB8-7EC832357ED8}
 static const GUID sLayerManagerCount =
 { 0x88041664, 0xc835, 0x4aa8, { 0xac, 0xb8, 0x7e, 0xc8, 0x32, 0x35, 0x7e, 0xd8 } };
 
 const FLOAT sBlendFactor[] = { 0, 0, 0, 0 };
 
+static const size_t kInitialMaximumTriangles = 64;
+
 namespace TexSlot {
   static const int RGB = 0;
   static const int Y = 1;
   static const int Cb = 2;
   static const int Cr = 3;
   static const int RGBWhite = 4;
   static const int Mask = 5;
   static const int Backdrop = 6;
@@ -79,31 +87,39 @@ struct DeviceAttachmentsD3D11
   bool InitSyncObject();
 
   typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11VertexShader>>
           VertexShaderArray;
   typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11PixelShader>>
           PixelShaderArray;
 
   RefPtr<ID3D11InputLayout> mInputLayout;
+  RefPtr<ID3D11InputLayout> mDynamicInputLayout;
+
   RefPtr<ID3D11Buffer> mVertexBuffer;
+  RefPtr<ID3D11Buffer> mDynamicVertexBuffer;
 
   VertexShaderArray mVSQuadShader;
   VertexShaderArray mVSQuadBlendShader;
+
+  VertexShaderArray mVSDynamicShader;
+  VertexShaderArray mVSDynamicBlendShader;
+
   PixelShaderArray mSolidColorShader;
   PixelShaderArray mRGBAShader;
   PixelShaderArray mRGBShader;
   PixelShaderArray mYCbCrShader;
   PixelShaderArray mComponentAlphaShader;
   PixelShaderArray mBlendShader;
   RefPtr<ID3D11Buffer> mPSConstantBuffer;
   RefPtr<ID3D11Buffer> mVSConstantBuffer;
   RefPtr<ID3D11RasterizerState> mRasterizerState;
   RefPtr<ID3D11SamplerState> mLinearSamplerState;
   RefPtr<ID3D11SamplerState> mPointSamplerState;
+
   RefPtr<ID3D11BlendState> mPremulBlendState;
   RefPtr<ID3D11BlendState> mNonPremulBlendState;
   RefPtr<ID3D11BlendState> mComponentBlendState;
   RefPtr<ID3D11BlendState> mDisabledBlendState;
   RefPtr<IDXGIResource> mSyncTexture;
   HANDLE mSyncHandle;
 
 private:
@@ -145,16 +161,17 @@ private:
 
 CompositorD3D11::CompositorD3D11(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget)
   : Compositor(aWidget, aParent)
   , mAttachments(nullptr)
   , mHwnd(nullptr)
   , mDisableSequenceForNextFrame(false)
   , mAllowPartialPresents(false)
   , mVerifyBuffersFailed(false)
+  , mMaximumTriangles(kInitialMaximumTriangles)
 {
 }
 
 CompositorD3D11::~CompositorD3D11()
 {
   if (mDevice) {
     int referenceCount = 0;
     UINT size = sizeof(referenceCount);
@@ -173,16 +190,84 @@ CompositorD3D11::~CompositorD3D11()
       // which hold a reference to the device.
       mDevice->SetPrivateData(sDeviceAttachmentsD3D11, 0, nullptr);
 
       delete attachments;
     }
   }
 }
 
+
+template<typename VertexType>
+void
+CompositorD3D11::SetVertexBuffer(ID3D11Buffer* aBuffer)
+{
+  UINT size = sizeof(VertexType);
+  UINT offset = 0;
+  mContext->IASetVertexBuffers(0, 1, &aBuffer, &size, &offset);
+}
+
+bool
+CompositorD3D11::SupportsLayerGeometry() const
+{
+  return gfxPrefs::D3D11LayerGeometry();
+}
+
+bool
+CompositorD3D11::UpdateDynamicVertexBuffer(const nsTArray<gfx::TexturedTriangle>& aTriangles)
+{
+  HRESULT hr;
+
+  // Resize the dynamic vertex buffer if needed.
+  if (aTriangles.Length() > mMaximumTriangles) {
+    CD3D11_BUFFER_DESC bufferDesc(sizeof(TexturedVertex) * aTriangles.Length() * 3,
+                                  D3D11_BIND_VERTEX_BUFFER,
+                                  D3D11_USAGE_DYNAMIC,
+                                  D3D11_CPU_ACCESS_WRITE);
+
+    hr = mDevice->CreateBuffer(&bufferDesc, nullptr,
+                               getter_AddRefs(mAttachments->mDynamicVertexBuffer));
+
+    if (Failed(hr, "resize dynamic vertex buffer")) {
+      return false;
+    }
+
+    mMaximumTriangles = aTriangles.Length();
+  }
+
+  MOZ_ASSERT(mMaximumTriangles >= aTriangles.Length());
+
+  D3D11_MAPPED_SUBRESOURCE resource {};
+  hr = mContext->Map(mAttachments->mDynamicVertexBuffer, 0,
+                     D3D11_MAP_WRITE_DISCARD, 0, &resource);
+
+  if (Failed(hr, "map dynamic vertex buffer")) {
+    return false;
+  }
+
+  const auto vertexFromPoints = [](const gfx::Point& p, const gfx::Point& t) {
+    return TexturedVertex { { p.x, p.y }, { t.x, t.y } };
+  };
+
+  nsTArray<TexturedVertex> vertices;
+
+  for (const gfx::TexturedTriangle& t : aTriangles) {
+    vertices.AppendElement(vertexFromPoints(t.p1, t.textureCoords.p1));
+    vertices.AppendElement(vertexFromPoints(t.p2, t.textureCoords.p2));
+    vertices.AppendElement(vertexFromPoints(t.p3, t.textureCoords.p3));
+  }
+
+  memcpy(resource.pData, vertices.Elements(),
+         vertices.Length() * sizeof(TexturedVertex));
+
+  mContext->Unmap(mAttachments->mDynamicVertexBuffer, 0);
+
+  return true;
+}
+
 bool
 CompositorD3D11::Initialize(nsCString* const out_failureReason)
 {
   ScopedGfxFeatureReporter reporter("D3D11 Layers");
 
   HRESULT hr;
 
   mDevice = DeviceManagerDx::Get()->GetCompositorDevice();
@@ -240,18 +325,47 @@ CompositorD3D11::Initialize(nsCString* c
     }
 
     Vertex vertices[] = { {{0.0, 0.0}}, {{1.0, 0.0}}, {{0.0, 1.0}}, {{1.0, 1.0}} };
     CD3D11_BUFFER_DESC bufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER);
     D3D11_SUBRESOURCE_DATA data;
     data.pSysMem = (void*)vertices;
 
     hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mAttachments->mVertexBuffer));
+    if (Failed(hr, "create vertex buffer")) {
+      *out_failureReason = "FEATURE_FAILURE_D3D11_VERTEX_BUFFER";
+      return false;
+    }
 
-    if (Failed(hr, "create vertex buffer")) {
+    // Create a second input layout for layers with dynamic geometry.
+    D3D11_INPUT_ELEMENT_DESC dynamicLayout[] =
+    {
+      { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+      { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+    };
+
+    hr = mDevice->CreateInputLayout(dynamicLayout,
+                                    sizeof(dynamicLayout) / sizeof(D3D11_INPUT_ELEMENT_DESC),
+                                    LayerDynamicVS,
+                                    sizeof(LayerDynamicVS),
+                                    getter_AddRefs(mAttachments->mDynamicInputLayout));
+
+    if (Failed(hr, "CreateInputLayout")) {
+      *out_failureReason = "FEATURE_FAILURE_D3D11_INPUT_LAYOUT";
+      return false;
+    }
+
+    // Allocate memory for the dynamic vertex buffer.
+    bufferDesc = CD3D11_BUFFER_DESC(sizeof(TexturedVertex) * mMaximumTriangles * 3,
+                                    D3D11_BIND_VERTEX_BUFFER,
+                                    D3D11_USAGE_DYNAMIC,
+                                    D3D11_CPU_ACCESS_WRITE);
+
+    hr = mDevice->CreateBuffer(&bufferDesc, nullptr, getter_AddRefs(mAttachments->mDynamicVertexBuffer));
+    if (Failed(hr, "create dynamic vertex buffer")) {
       *out_failureReason = "FEATURE_FAILURE_D3D11_VERTEX_BUFFER";
       return false;
     }
 
     if (!mAttachments->CreateShaders()) {
       *out_failureReason = "FEATURE_FAILURE_D3D11_CREATE_SHADERS";
       return false;
     }
@@ -628,18 +742,24 @@ CompositorD3D11::SetRenderTarget(Composi
     newRT->GetProjection(projection, depthEnable, zNear, zFar);
     PrepareViewport(newRT->GetSize(), projection, zNear, zFar);
   } else {
     PrepareViewport(newRT->GetSize());
   }
 }
 
 ID3D11PixelShader*
-CompositorD3D11::GetPSForEffect(Effect* aEffect, MaskType aMaskType)
+CompositorD3D11::GetPSForEffect(Effect* aEffect,
+                                const bool aUseBlendShader,
+                                const MaskType aMaskType)
 {
+  if (aUseBlendShader) {
+    return mAttachments->mBlendShader[MaskType::MaskNone];
+  }
+
   switch (aEffect->mType) {
   case EffectTypes::SOLID_COLOR:
     return mAttachments->mSolidColorShader[aMaskType];
   case EffectTypes::RENDER_TARGET:
     return mAttachments->mRGBAShader[aMaskType];
   case EffectTypes::RGB: {
     SurfaceFormat format = static_cast<TexturedEffect*>(aEffect)->mTexture->GetFormat();
     return (format == SurfaceFormat::B8G8R8A8 || format == SurfaceFormat::R8G8B8A8)
@@ -728,16 +848,126 @@ EffectToBlendLayerType(Effect* aEffect)
 void
 CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
                           const gfx::IntRect& aClipRect,
                           const EffectChain& aEffectChain,
                           gfx::Float aOpacity,
                           const gfx::Matrix4x4& aTransform,
                           const gfx::Rect& aVisibleRect)
 {
+  DrawGeometry(aRect, aRect, aClipRect, aEffectChain,
+               aOpacity, aTransform, aVisibleRect);
+}
+
+void
+CompositorD3D11::DrawTriangles(const nsTArray<gfx::TexturedTriangle>& aTriangles,
+                               const gfx::Rect& aRect,
+                               const gfx::IntRect& aClipRect,
+                               const EffectChain& aEffectChain,
+                               gfx::Float aOpacity,
+                               const gfx::Matrix4x4& aTransform,
+                               const gfx::Rect& aVisibleRect)
+{
+  DrawGeometry(aTriangles, aRect, aClipRect, aEffectChain,
+               aOpacity, aTransform, aVisibleRect);
+}
+
+void
+CompositorD3D11::PrepareDynamicVertexBuffer()
+{
+  mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+  mContext->IASetInputLayout(mAttachments->mDynamicInputLayout);
+  SetVertexBuffer<TexturedVertex>(mAttachments->mDynamicVertexBuffer);
+}
+
+void
+CompositorD3D11::PrepareStaticVertexBuffer()
+{
+  mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+  mContext->IASetInputLayout(mAttachments->mInputLayout);
+  SetVertexBuffer<Vertex>(mAttachments->mVertexBuffer);
+}
+
+void
+CompositorD3D11::Draw(const nsTArray<gfx::TexturedTriangle>& aTriangles,
+                      const gfx::Rect*)
+{
+  if (!UpdateConstantBuffers()) {
+    NS_WARNING("Failed to update shader constant buffers");
+    return;
+  }
+
+  PrepareDynamicVertexBuffer();
+
+  if (!UpdateDynamicVertexBuffer(aTriangles)) {
+    NS_WARNING("Failed to update shader dynamic buffers");
+    return;
+  }
+
+  mContext->Draw(3 * aTriangles.Length(), 0);
+
+  PrepareStaticVertexBuffer();
+}
+
+void
+CompositorD3D11::Draw(const gfx::Rect& aRect,
+                      const gfx::Rect* aTexCoords)
+{
+  Rect layerRects[4] = { aRect };
+  Rect textureRects[4] = { };
+  size_t rects = 1;
+
+  if (aTexCoords) {
+    rects = DecomposeIntoNoRepeatRects(aRect, *aTexCoords,
+                                       &layerRects, &textureRects);
+  }
+
+  for (size_t i = 0; i < rects; i++) {
+    mVSConstants.layerQuad = layerRects[i];
+    mVSConstants.textureCoords = textureRects[i];
+
+    if (!UpdateConstantBuffers()) {
+      NS_WARNING("Failed to update shader constant buffers");
+      break;
+    }
+
+    mContext->Draw(4, 0);
+  }
+}
+
+ID3D11VertexShader*
+CompositorD3D11::GetVSForGeometry(const nsTArray<gfx::TexturedTriangle>& aTriangles,
+                                  const bool aUseBlendShaders,
+                                  const MaskType aMaskType)
+{
+  return aUseBlendShaders
+    ? mAttachments->mVSDynamicBlendShader[aMaskType]
+    : mAttachments->mVSDynamicShader[aMaskType];
+}
+
+ID3D11VertexShader*
+CompositorD3D11::GetVSForGeometry(const gfx::Rect& aRect,
+                                  const bool aUseBlendShaders,
+                                  const MaskType aMaskType)
+{
+  return aUseBlendShaders
+    ? mAttachments->mVSQuadBlendShader[aMaskType]
+    : mAttachments->mVSQuadShader[aMaskType];
+}
+
+template<typename Geometry>
+void
+CompositorD3D11::DrawGeometry(const Geometry& aGeometry,
+                              const gfx::Rect& aRect,
+                              const gfx::IntRect& aClipRect,
+                              const EffectChain& aEffectChain,
+                              gfx::Float aOpacity,
+                              const gfx::Matrix4x4& aTransform,
+                              const gfx::Rect& aVisibleRect)
+{
   if (mCurrentClip.IsEmpty()) {
     return;
   }
 
   MOZ_ASSERT(mCurrentRT, "No render target");
 
   memcpy(&mVSConstants.layerTransform, &aTransform._11, 64);
   IntPoint origin = mCurrentRT->GetOrigin();
@@ -783,19 +1013,17 @@ CompositorD3D11::DrawQuad(const gfx::Rec
     return;
   }
 
   scissor.left = clipRect.x;
   scissor.right = clipRect.XMost();
   scissor.top = clipRect.y;
   scissor.bottom = clipRect.YMost();
 
-  RefPtr<ID3D11VertexShader> vertexShader = mAttachments->mVSQuadShader[maskType];
-  RefPtr<ID3D11PixelShader> pixelShader = GetPSForEffect(aEffectChain.mPrimaryEffect, maskType);
-
+  bool useBlendShaders = false;
   RefPtr<ID3D11Texture2D> mixBlendBackdrop;
   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;
 
     // If the blend operation needs to read from the backdrop, copy the
@@ -803,34 +1031,39 @@ CompositorD3D11::DrawQuad(const gfx::Rec
     if (BlendOpIsMixBlendMode(blendMode)) {
       gfx::Matrix4x4 backdropTransform;
       gfx::IntRect rect = ComputeBackdropCopyRect(aRect, aClipRect, aTransform, &backdropTransform);
 
       RefPtr<ID3D11ShaderResourceView> srv;
       if (CopyBackdrop(rect, &mixBlendBackdrop, &srv) &&
           mAttachments->InitBlendShaders())
       {
-        vertexShader = mAttachments->mVSQuadBlendShader[maskType];
-        pixelShader = mAttachments->mBlendShader[MaskType::MaskNone];
+        useBlendShaders = true;
 
         ID3D11ShaderResourceView* srView = srv.get();
         mContext->PSSetShaderResources(TexSlot::Backdrop, 1, &srView);
 
         memcpy(&mVSConstants.backdropTransform, &backdropTransform._11, 64);
 
         mPSConstants.blendConfig[0] = EffectToBlendLayerType(aEffectChain.mPrimaryEffect);
         mPSConstants.blendConfig[1] = int(maskType);
         mPSConstants.blendConfig[2] = BlendOpToShaderConstant(blendMode);
         mPSConstants.blendConfig[3] = EffectHasPremultipliedAlpha(aEffectChain.mPrimaryEffect);
       }
     }
   }
 
   mContext->RSSetScissorRects(1, &scissor);
-  mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+
+  RefPtr<ID3D11VertexShader> vertexShader =
+    GetVSForGeometry(aGeometry, useBlendShaders, maskType);
+
+  RefPtr<ID3D11PixelShader> pixelShader =
+    GetPSForEffect(aEffectChain.mPrimaryEffect, useBlendShaders, maskType);
+
   mContext->VSSetShader(vertexShader, nullptr, 0);
   mContext->PSSetShader(pixelShader, nullptr, 0);
 
   const Rect* pTexCoordRect = nullptr;
 
   switch (aEffectChain.mPrimaryEffect->mType) {
   case EffectTypes::SOLID_COLOR: {
       Color color =
@@ -930,42 +1163,17 @@ CompositorD3D11::DrawQuad(const gfx::Rec
       restoreBlendMode = true;
     }
     break;
   default:
     NS_WARNING("Unknown shader type");
     return;
   }
 
-  if (pTexCoordRect) {
-    Rect layerRects[4];
-    Rect textureRects[4];
-    size_t rects = DecomposeIntoNoRepeatRects(aRect,
-                                              *pTexCoordRect,
-                                              &layerRects,
-                                              &textureRects);
-    for (size_t i = 0; i < rects; i++) {
-      mVSConstants.layerQuad = layerRects[i];
-      mVSConstants.textureCoords = textureRects[i];
-
-      if (!UpdateConstantBuffers()) {
-        NS_WARNING("Failed to update shader constant buffers");
-        break;
-      }
-      mContext->Draw(4, 0);
-    }
-  } else {
-    mVSConstants.layerQuad = aRect;
-
-    if (!UpdateConstantBuffers()) {
-      NS_WARNING("Failed to update shader constant buffers");
-    } else {
-      mContext->Draw(4, 0);
-    }
-  }
+  Draw(aGeometry, pTexCoordRect);
 
   if (restoreBlendMode) {
     mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
   }
 }
 
 void
 CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
@@ -1029,22 +1237,17 @@ CompositorD3D11::BeginFrame(const nsIntR
   }
 
   if (clipRect.IsEmpty()) {
     CancelFrame();
     *aRenderBoundsOut = IntRect();
     return;
   }
 
-  mContext->IASetInputLayout(mAttachments->mInputLayout);
-
-  ID3D11Buffer* buffer = mAttachments->mVertexBuffer;
-  UINT size = sizeof(Vertex);
-  UINT offset = 0;
-  mContext->IASetVertexBuffers(0, 1, &buffer, &size, &offset);
+  PrepareStaticVertexBuffer();
 
   mInvalidRect = IntRect(invalidRect.x, invalidRect.y, invalidRect.width, invalidRect.height);
   mInvalidRegion = invalidRegionSafe;
 
   if (aClipRectOut) {
     *aClipRectOut = IntRect(0, 0, mSize.width, mSize.height);
   }
   if (aRenderBoundsOut) {
@@ -1399,28 +1602,37 @@ DeviceAttachmentsD3D11::InitSyncObject()
 
 bool
 DeviceAttachmentsD3D11::InitBlendShaders()
 {
   if (!mVSQuadBlendShader[MaskType::MaskNone]) {
     InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone);
     InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask);
   }
+
+  if (!mVSDynamicBlendShader[MaskType::MaskNone]) {
+    InitVertexShader(sLayerDynamicBlendVS, mVSDynamicBlendShader, MaskType::MaskNone);
+    InitVertexShader(sLayerDynamicBlendMaskVS, mVSDynamicBlendShader, MaskType::Mask);
+  }
+
   if (!mBlendShader[MaskType::MaskNone]) {
     InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone);
   }
   return mInitOkay;
 }
 
 bool
 DeviceAttachmentsD3D11::CreateShaders()
 {
   InitVertexShader(sLayerQuadVS, mVSQuadShader, MaskType::MaskNone);
   InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask);
 
+  InitVertexShader(sLayerDynamicVS, mVSDynamicShader, MaskType::MaskNone);
+  InitVertexShader(sLayerDynamicMaskVS, mVSDynamicShader, MaskType::Mask);
+
   InitPixelShader(sSolidColorShader, mSolidColorShader, MaskType::MaskNone);
   InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask);
   InitPixelShader(sRGBShader, mRGBShader, MaskType::MaskNone);
   InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask);
   InitPixelShader(sRGBAShader, mRGBAShader, MaskType::MaskNone);
   InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask);
   InitPixelShader(sYCbCrShader, mYCbCrShader, MaskType::MaskNone);
   InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask);
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -96,17 +96,17 @@ public:
                         const gfx::IntRect &aClipRect,
                         const EffectChain &aEffectChain,
                         gfx::Float aOpacity,
                         const gfx::Matrix4x4& aTransform,
                         const gfx::Rect& aVisibleRect) override;
 
   /**
    * Start a new frame. If aClipRectIn is null, sets *aClipRectOut to the
-   * screen dimensions. 
+   * screen dimensions.
    */
   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;
 
@@ -122,16 +122,18 @@ public:
    * to a window of the given dimensions.
    */
   virtual void PrepareViewport(const gfx::IntSize& aSize);
   virtual void PrepareViewport(const gfx::IntSize& aSize, const gfx::Matrix4x4& aProjection,
                                float aZNear, float aZFar);
 
   virtual bool SupportsPartialTextureUpdate() override { return true; }
 
+  virtual bool SupportsLayerGeometry() const override;
+
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "Direct3D 11"; }
 #endif
 
   virtual LayersBackend GetBackendType() const override {
     return LayersBackend::LAYERS_D3D11;
   }
 
@@ -155,25 +157,68 @@ private:
   bool Failed(HRESULT hr, const char* aContext);
 
   // ensure mSize is up to date with respect to mWidget
   void EnsureSize();
   bool VerifyBufferSize();
   bool UpdateRenderTarget();
   bool UpdateConstantBuffers();
   void SetSamplerForSamplingFilter(gfx::SamplingFilter aSamplingFilter);
-  ID3D11PixelShader* GetPSForEffect(Effect *aEffect, MaskType aMaskType);
+
+  ID3D11PixelShader* GetPSForEffect(Effect* aEffect,
+                                    const bool aUseBlendShader,
+                                    const MaskType aMaskType);
   void PaintToTarget();
   RefPtr<ID3D11Texture2D> CreateTexture(const gfx::IntRect& aRect,
                                         const CompositingRenderTarget* aSource,
                                         const gfx::IntPoint& aSourcePoint);
   bool CopyBackdrop(const gfx::IntRect& aRect,
                     RefPtr<ID3D11Texture2D>* aOutTexture,
                     RefPtr<ID3D11ShaderResourceView>* aOutView);
 
+  virtual void DrawTriangles(const nsTArray<gfx::TexturedTriangle>& aTriangles,
+                             const gfx::Rect& aRect,
+                             const gfx::IntRect& aClipRect,
+                             const EffectChain& aEffectChain,
+                             gfx::Float aOpacity,
+                             const gfx::Matrix4x4& aTransform,
+                             const gfx::Rect& aVisibleRect) override;
+
+  template<typename Geometry>
+  void DrawGeometry(const Geometry& aGeometry,
+                    const gfx::Rect& aRect,
+                    const gfx::IntRect& aClipRect,
+                    const EffectChain& aEffectChain,
+                    gfx::Float aOpacity,
+                    const gfx::Matrix4x4& aTransform,
+                    const gfx::Rect& aVisibleRect);
+
+  bool UpdateDynamicVertexBuffer(const nsTArray<gfx::TexturedTriangle>& aTriangles);
+
+  void PrepareDynamicVertexBuffer();
+  void PrepareStaticVertexBuffer();
+
+  // Overloads for rendering both rects and triangles with same rendering path
+  void Draw(const nsTArray<gfx::TexturedTriangle>& aGeometry,
+            const gfx::Rect* aTexCoords);
+
+  void Draw(const gfx::Rect& aGeometry,
+            const gfx::Rect* aTexCoords);
+
+  ID3D11VertexShader* GetVSForGeometry(const nsTArray<gfx::TexturedTriangle>& aTriangles,
+                                       const bool aUseBlendShader,
+                                       const MaskType aMaskType);
+
+  ID3D11VertexShader* GetVSForGeometry(const gfx::Rect& aRect,
+                                       const bool aUseBlendShader,
+                                       const MaskType aMaskType);
+
+  template<typename VertexType>
+  void SetVertexBuffer(ID3D11Buffer* aBuffer);
+
   RefPtr<ID3D11DeviceContext> mContext;
   RefPtr<ID3D11Device> mDevice;
   RefPtr<IDXGISwapChain> mSwapChain;
   RefPtr<CompositingRenderTargetD3D11> mDefaultRT;
   RefPtr<CompositingRenderTargetD3D11> mCurrentRT;
 
   RefPtr<ID3D11Query> mQuery;
 
@@ -191,14 +236,16 @@ private:
   bool mAllowPartialPresents;
 
   gfx::IntRect mInvalidRect;
   // This is the clip rect applied to the default DrawTarget (i.e. the window)
   gfx::IntRect mCurrentClip;
   nsIntRegion mInvalidRegion;
 
   bool mVerifyBuffersFailed;
+
+  size_t mMaximumTriangles;
 };
 
 }
 }
 
 #endif