summaryrefslogtreecommitdiffstats
path: root/dom/plugins/ipc/D3D11SurfaceHolder.cpp
blob: 429f3be6731d4cb0a7741ab5b26bfcd4a33d2fa5 (plain)
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
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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 "nsDebug.h"
#include "D3D11SurfaceHolder.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/layers/TextureD3D11.h"
#include <d3d11.h>

namespace mozilla {
namespace plugins {

using namespace mozilla::gfx;
using namespace mozilla::layers;

D3D11SurfaceHolder::D3D11SurfaceHolder(ID3D11Texture2D* back,
                                       SurfaceFormat format,
                                       const IntSize& size)
    : mDevice11(DeviceManagerDx::Get()->GetContentDevice()),
      mBack(back),
      mFormat(format),
      mSize(size) {}

D3D11SurfaceHolder::~D3D11SurfaceHolder() {}

bool D3D11SurfaceHolder::IsValid() {
  // If a TDR occurred, platform devices will be recreated.
  if (DeviceManagerDx::Get()->GetContentDevice() != mDevice11) {
    return false;
  }
  return true;
}

bool D3D11SurfaceHolder::CopyToTextureClient(TextureClient* aClient) {
  MOZ_ASSERT(NS_IsMainThread());

  D3D11TextureData* data = aClient->GetInternalData()->AsD3D11TextureData();
  if (!data) {
    // We don't support this yet. We expect to have a D3D11 compositor, and
    // therefore D3D11 surfaces.
    NS_WARNING("Plugin DXGI surface has unsupported TextureClient");
    return false;
  }

  RefPtr<ID3D11DeviceContext> context;
  mDevice11->GetImmediateContext(getter_AddRefs(context));
  if (!context) {
    NS_WARNING("Could not get an immediate D3D11 context");
    return false;
  }

  TextureClientAutoLock autoLock(aClient, OpenMode::OPEN_WRITE_ONLY);
  if (!autoLock.Succeeded()) {
    return false;
  }

  RefPtr<IDXGIKeyedMutex> mutex;
  HRESULT hr = mBack->QueryInterface(__uuidof(IDXGIKeyedMutex),
                                     (void**)getter_AddRefs(mutex));
  if (FAILED(hr) || !mutex) {
    NS_WARNING("Could not acquire an IDXGIKeyedMutex");
    return false;
  }

  {
    AutoTextureLock lock(mutex, hr);
    if (hr == WAIT_ABANDONED || hr == WAIT_TIMEOUT || FAILED(hr)) {
      NS_WARNING(
          "Could not acquire DXGI surface lock - plugin forgot to release?");
      return false;
    }

    context->CopyResource(data->GetD3D11Texture(), mBack);
  }
  return true;
}

}  // namespace plugins
}  // namespace mozilla