gfx/layers/d3d10/LayerManagerD3D10.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,894 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include <algorithm>
    1.10 +
    1.11 +#include "LayerManagerD3D10.h"
    1.12 +#include "LayerManagerD3D10Effect.h"
    1.13 +#include "gfxWindowsPlatform.h"
    1.14 +#include "gfx2DGlue.h"
    1.15 +#include "gfxD2DSurface.h"
    1.16 +#include "gfxFailure.h"
    1.17 +#include "cairo-win32.h"
    1.18 +#include "dxgi.h"
    1.19 +
    1.20 +#include "ContainerLayerD3D10.h"
    1.21 +#include "ThebesLayerD3D10.h"
    1.22 +#include "ColorLayerD3D10.h"
    1.23 +#include "CanvasLayerD3D10.h"
    1.24 +#include "ReadbackLayerD3D10.h"
    1.25 +#include "ImageLayerD3D10.h"
    1.26 +#include "mozilla/layers/PLayerChild.h"
    1.27 +#include "mozilla/WidgetUtils.h"
    1.28 +
    1.29 +#include "../d3d9/Nv3DVUtils.h"
    1.30 +
    1.31 +#include "gfxCrashReporterUtils.h"
    1.32 +#include "nsWindowsHelpers.h"
    1.33 +#ifdef MOZ_METRO
    1.34 +#include "DXGI1_2.h"
    1.35 +#endif
    1.36 +
    1.37 +using namespace std;
    1.38 +using namespace mozilla::dom;
    1.39 +using namespace mozilla::gfx;
    1.40 +
    1.41 +namespace mozilla {
    1.42 +namespace layers {
    1.43 +
    1.44 +struct Vertex
    1.45 +{
    1.46 +    float position[2];
    1.47 +};
    1.48 +
    1.49 +// {592BF306-0EED-4F76-9D03-A0846450F472}
    1.50 +static const GUID sDeviceAttachments = 
    1.51 +{ 0x592bf306, 0xeed, 0x4f76, { 0x9d, 0x3, 0xa0, 0x84, 0x64, 0x50, 0xf4, 0x72 } };
    1.52 +// {716AEDB1-C9C3-4B4D-8332-6F65D44AF6A8}
    1.53 +static const GUID sLayerManagerCount = 
    1.54 +{ 0x716aedb1, 0xc9c3, 0x4b4d, { 0x83, 0x32, 0x6f, 0x65, 0xd4, 0x4a, 0xf6, 0xa8 } };
    1.55 +
    1.56 +LayerManagerD3D10::LayerManagerD3D10(nsIWidget *aWidget)
    1.57 +  : mWidget(aWidget)
    1.58 +  , mDisableSequenceForNextFrame(false)
    1.59 +{
    1.60 +}
    1.61 +
    1.62 +struct DeviceAttachments
    1.63 +{
    1.64 +  nsRefPtr<ID3D10Effect> mEffect;
    1.65 +  nsRefPtr<ID3D10InputLayout> mInputLayout;
    1.66 +  nsRefPtr<ID3D10Buffer> mVertexBuffer;
    1.67 +  nsRefPtr<ReadbackManagerD3D10> mReadbackManager;
    1.68 +};
    1.69 +
    1.70 +LayerManagerD3D10::~LayerManagerD3D10()
    1.71 +{
    1.72 +  if (mDevice) {
    1.73 +    int referenceCount = 0;
    1.74 +    UINT size = sizeof(referenceCount);
    1.75 +    HRESULT hr = mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
    1.76 +    NS_ASSERTION(SUCCEEDED(hr), "Reference count not found on device.");
    1.77 +    referenceCount--;
    1.78 +    mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount);
    1.79 +
    1.80 +    if (!referenceCount) {
    1.81 +      DeviceAttachments *attachments;
    1.82 +      size = sizeof(attachments);
    1.83 +      mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments);
    1.84 +      // No LayerManagers left for this device. Clear out interfaces stored which
    1.85 +      // hold a reference to the device.
    1.86 +      mDevice->SetPrivateData(sDeviceAttachments, 0, nullptr);
    1.87 +
    1.88 +      delete attachments;
    1.89 +    }
    1.90 +  }
    1.91 +
    1.92 +  Destroy();
    1.93 +}
    1.94 +
    1.95 +static inline void
    1.96 +SetHRESULT(HRESULT* aHresultPtr, HRESULT aHresult)
    1.97 +{
    1.98 +  if (aHresultPtr) {
    1.99 +    *aHresultPtr = aHresult;
   1.100 +  }
   1.101 +}
   1.102 + 
   1.103 +bool
   1.104 +LayerManagerD3D10::Initialize(bool force, HRESULT* aHresultPtr)
   1.105 +{
   1.106 +  ScopedGfxFeatureReporter reporter("D3D10 Layers", force);
   1.107 +
   1.108 +  HRESULT hr = E_UNEXPECTED;
   1.109 +
   1.110 +  /* Create an Nv3DVUtils instance */
   1.111 +  if (!mNv3DVUtils) {
   1.112 +    mNv3DVUtils = new Nv3DVUtils();
   1.113 +    if (!mNv3DVUtils) {
   1.114 +      NS_WARNING("Could not create a new instance of Nv3DVUtils.\n");
   1.115 +    }
   1.116 +  }
   1.117 +
   1.118 +  /* Initialize the Nv3DVUtils object */
   1.119 +  if (mNv3DVUtils) {
   1.120 +    mNv3DVUtils->Initialize();
   1.121 +  }
   1.122 +
   1.123 +  mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
   1.124 +  if (!mDevice) {
   1.125 +      SetHRESULT(aHresultPtr, hr);
   1.126 +      return false;
   1.127 +  }
   1.128 +
   1.129 +  /*
   1.130 +   * Do some post device creation setup
   1.131 +   */
   1.132 +  if (mNv3DVUtils) {
   1.133 +    IUnknown* devUnknown = nullptr;
   1.134 +    if (mDevice) {
   1.135 +      mDevice->QueryInterface(IID_IUnknown, (void **)&devUnknown);
   1.136 +    }
   1.137 +    mNv3DVUtils->SetDeviceInfo(devUnknown);
   1.138 +  }
   1.139 +
   1.140 +  int referenceCount = 0;
   1.141 +  UINT size = sizeof(referenceCount);
   1.142 +  // If this isn't there yet it'll fail, count will remain 0, which is correct.
   1.143 +  mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
   1.144 +  referenceCount++;
   1.145 +  mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount);
   1.146 +
   1.147 +  DeviceAttachments *attachments;
   1.148 +  size = sizeof(DeviceAttachments*);
   1.149 +  if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) {
   1.150 +    attachments = new DeviceAttachments;
   1.151 +    mDevice->SetPrivateData(sDeviceAttachments, sizeof(attachments), &attachments);
   1.152 +
   1.153 +    SetLastError(0);
   1.154 +    decltype(D3D10CreateEffectFromMemory)* createEffect =
   1.155 +      (decltype(D3D10CreateEffectFromMemory)*)
   1.156 +        GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateEffectFromMemory");
   1.157 +    if (!createEffect) {
   1.158 +      SetHRESULT(aHresultPtr, HRESULT_FROM_WIN32(GetLastError()));
   1.159 +      return false;
   1.160 +    }
   1.161 +
   1.162 +    hr = createEffect((void*)g_main,
   1.163 +                      sizeof(g_main),
   1.164 +                      D3D10_EFFECT_SINGLE_THREADED,
   1.165 +                      mDevice,
   1.166 +                      nullptr,
   1.167 +                      getter_AddRefs(mEffect));
   1.168 +    
   1.169 +    if (FAILED(hr)) {
   1.170 +      SetHRESULT(aHresultPtr, hr);
   1.171 +      return false;
   1.172 +    }
   1.173 +
   1.174 +    attachments->mEffect = mEffect;
   1.175 +  
   1.176 +    D3D10_INPUT_ELEMENT_DESC layout[] =
   1.177 +    {
   1.178 +      { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
   1.179 +    };
   1.180 +    D3D10_PASS_DESC passDesc;
   1.181 +    mEffect->GetTechniqueByName("RenderRGBLayerPremul")->GetPassByIndex(0)->
   1.182 +      GetDesc(&passDesc);
   1.183 +
   1.184 +    hr = mDevice->CreateInputLayout(layout,
   1.185 +                                    sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC),
   1.186 +                                    passDesc.pIAInputSignature,
   1.187 +                                    passDesc.IAInputSignatureSize,
   1.188 +                                    getter_AddRefs(mInputLayout));
   1.189 +    
   1.190 +    if (FAILED(hr)) {
   1.191 +      SetHRESULT(aHresultPtr, hr);
   1.192 +      return false;
   1.193 +    }
   1.194 +
   1.195 +    attachments->mInputLayout = mInputLayout;
   1.196 +  
   1.197 +    Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} };
   1.198 +    CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
   1.199 +    D3D10_SUBRESOURCE_DATA data;
   1.200 +    data.pSysMem = (void*)vertices;
   1.201 +
   1.202 +    hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mVertexBuffer));
   1.203 +
   1.204 +    if (FAILED(hr)) {
   1.205 +      SetHRESULT(aHresultPtr, hr);
   1.206 +      return false;
   1.207 +    }
   1.208 +
   1.209 +    attachments->mVertexBuffer = mVertexBuffer;
   1.210 +  } else {
   1.211 +    mEffect = attachments->mEffect;
   1.212 +    mVertexBuffer = attachments->mVertexBuffer;
   1.213 +    mInputLayout = attachments->mInputLayout;
   1.214 +  }
   1.215 +
   1.216 +  nsRefPtr<IDXGIDevice> dxgiDevice;
   1.217 +  nsRefPtr<IDXGIAdapter> dxgiAdapter;
   1.218 +
   1.219 +  mDevice->QueryInterface(dxgiDevice.StartAssignment());
   1.220 +  dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
   1.221 +  
   1.222 +#ifdef MOZ_METRO
   1.223 +  if (IsRunningInWindowsMetro()) {
   1.224 +    nsRefPtr<IDXGIFactory2> dxgiFactory;
   1.225 +    dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
   1.226 +
   1.227 +    nsIntRect rect;
   1.228 +    mWidget->GetClientBounds(rect);
   1.229 +
   1.230 +    DXGI_SWAP_CHAIN_DESC1 swapDesc = { 0 };
   1.231 +    // Automatically detect the width and the height from the winrt CoreWindow
   1.232 +    swapDesc.Width = rect.width;
   1.233 +    swapDesc.Height = rect.height;
   1.234 +    // This is the most common swapchain format
   1.235 +    swapDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
   1.236 +    swapDesc.Stereo = false; 
   1.237 +    // Don't use multi-sampling
   1.238 +    swapDesc.SampleDesc.Count = 1;
   1.239 +    swapDesc.SampleDesc.Quality = 0;
   1.240 +    swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
   1.241 +    // Use double buffering to enable flip
   1.242 +    swapDesc.BufferCount = 2;
   1.243 +    swapDesc.Scaling = DXGI_SCALING_NONE;
   1.244 +    // All Metro style apps must use this SwapEffect
   1.245 +    swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
   1.246 +    swapDesc.Flags = 0;
   1.247 +
   1.248 +    /**
   1.249 +     * Create a swap chain, this swap chain will contain the backbuffer for
   1.250 +     * the window we draw to. The front buffer is the full screen front
   1.251 +     * buffer.
   1.252 +    */
   1.253 +    nsRefPtr<IDXGISwapChain1> swapChain1;
   1.254 +    hr = dxgiFactory->CreateSwapChainForCoreWindow(
   1.255 +           dxgiDevice, (IUnknown *)mWidget->GetNativeData(NS_NATIVE_ICOREWINDOW),
   1.256 +           &swapDesc, nullptr, getter_AddRefs(swapChain1));
   1.257 +    if (FAILED(hr)) {
   1.258 +      SetHRESULT(aHresultPtr, hr);
   1.259 +      return false;
   1.260 +    }
   1.261 +    mSwapChain = swapChain1;
   1.262 +  } else
   1.263 +#endif
   1.264 +  {
   1.265 +    nsRefPtr<IDXGIFactory> dxgiFactory;
   1.266 +    dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
   1.267 +
   1.268 +    DXGI_SWAP_CHAIN_DESC swapDesc;
   1.269 +    ::ZeroMemory(&swapDesc, sizeof(swapDesc));
   1.270 +    swapDesc.BufferDesc.Width = 0;
   1.271 +    swapDesc.BufferDesc.Height = 0;
   1.272 +    swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
   1.273 +    swapDesc.BufferDesc.RefreshRate.Numerator = 60;
   1.274 +    swapDesc.BufferDesc.RefreshRate.Denominator = 1;
   1.275 +    swapDesc.SampleDesc.Count = 1;
   1.276 +    swapDesc.SampleDesc.Quality = 0;
   1.277 +    swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
   1.278 +    swapDesc.BufferCount = 1;
   1.279 +    swapDesc.OutputWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
   1.280 +    swapDesc.Windowed = TRUE;
   1.281 +    // We don't really need this flag, however it seems on some NVidia hardware
   1.282 +    // smaller area windows do not present properly without this flag. This flag
   1.283 +    // should have no negative consequences by itself. See bug 613790. This flag
   1.284 +    // is broken on optimus devices. As a temporary solution we don't set it
   1.285 +    // there, the only way of reliably detecting we're on optimus is looking for
   1.286 +    // the DLL. See Bug 623807.
   1.287 +    if (gfxWindowsPlatform::IsOptimus()) {
   1.288 +      swapDesc.Flags = 0;
   1.289 +    } else {
   1.290 +      swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
   1.291 +    }
   1.292 +
   1.293 +    /**
   1.294 +     * Create a swap chain, this swap chain will contain the backbuffer for
   1.295 +     * the window we draw to. The front buffer is the full screen front
   1.296 +     * buffer.
   1.297 +    */
   1.298 +    hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, getter_AddRefs(mSwapChain));
   1.299 +    if (FAILED(hr)) {
   1.300 +     return false;
   1.301 +    }
   1.302 +
   1.303 +    // We need this because we don't want DXGI to respond to Alt+Enter.
   1.304 +    dxgiFactory->MakeWindowAssociation(swapDesc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES);
   1.305 +  }
   1.306 +
   1.307 +  reporter.SetSuccessful();
   1.308 +  return true;
   1.309 +}
   1.310 +
   1.311 +void
   1.312 +LayerManagerD3D10::Destroy()
   1.313 +{
   1.314 +  if (!IsDestroyed()) {
   1.315 +    if (mRoot) {
   1.316 +      static_cast<LayerD3D10*>(mRoot->ImplData())->LayerManagerDestroyed();
   1.317 +    }
   1.318 +    // XXX need to be careful here about surface destruction
   1.319 +    // racing with share-to-chrome message
   1.320 +  }
   1.321 +  LayerManager::Destroy();
   1.322 +}
   1.323 +
   1.324 +void
   1.325 +LayerManagerD3D10::SetRoot(Layer *aRoot)
   1.326 +{
   1.327 +  mRoot = aRoot;
   1.328 +}
   1.329 +
   1.330 +void
   1.331 +LayerManagerD3D10::BeginTransaction()
   1.332 +{
   1.333 +  mInTransaction = true;
   1.334 +
   1.335 +#ifdef MOZ_LAYERS_HAVE_LOG
   1.336 +  MOZ_LAYERS_LOG(("[----- BeginTransaction"));
   1.337 +  Log();
   1.338 +#endif
   1.339 +}
   1.340 +
   1.341 +void
   1.342 +LayerManagerD3D10::BeginTransactionWithTarget(gfxContext* aTarget)
   1.343 +{
   1.344 +  mInTransaction = true;
   1.345 +  mTarget = aTarget;
   1.346 +}
   1.347 +
   1.348 +bool
   1.349 +LayerManagerD3D10::EndEmptyTransaction(EndTransactionFlags aFlags)
   1.350 +{
   1.351 +  mInTransaction = false;
   1.352 +
   1.353 +  if (!mRoot)
   1.354 +    return false;
   1.355 +
   1.356 +  EndTransaction(nullptr, nullptr, aFlags);
   1.357 +  return true;
   1.358 +}
   1.359 +
   1.360 +void
   1.361 +LayerManagerD3D10::EndTransaction(DrawThebesLayerCallback aCallback,
   1.362 +                                  void* aCallbackData,
   1.363 +                                  EndTransactionFlags aFlags)
   1.364 +{
   1.365 +  mInTransaction = false;
   1.366 +
   1.367 +  if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
   1.368 +    mCurrentCallbackInfo.Callback = aCallback;
   1.369 +    mCurrentCallbackInfo.CallbackData = aCallbackData;
   1.370 +
   1.371 +    if (aFlags & END_NO_COMPOSITE) {
   1.372 +      // Apply pending tree updates before recomputing effective
   1.373 +      // properties.
   1.374 +      mRoot->ApplyPendingUpdatesToSubtree();
   1.375 +    }
   1.376 +
   1.377 +    // The results of our drawing always go directly into a pixel buffer,
   1.378 +    // so we don't need to pass any global transform here.
   1.379 +    mRoot->ComputeEffectiveTransforms(Matrix4x4());
   1.380 +
   1.381 +#ifdef MOZ_LAYERS_HAVE_LOG
   1.382 +    MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   1.383 +    Log();
   1.384 +#endif
   1.385 +
   1.386 +    Render(aFlags);
   1.387 +    mCurrentCallbackInfo.Callback = nullptr;
   1.388 +    mCurrentCallbackInfo.CallbackData = nullptr;
   1.389 +  }
   1.390 +
   1.391 +#ifdef MOZ_LAYERS_HAVE_LOG
   1.392 +  Log();
   1.393 +  MOZ_LAYERS_LOG(("]----- EndTransaction"));
   1.394 +#endif
   1.395 +
   1.396 +  mTarget = nullptr;
   1.397 +}
   1.398 +
   1.399 +already_AddRefed<ThebesLayer>
   1.400 +LayerManagerD3D10::CreateThebesLayer()
   1.401 +{
   1.402 +  nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D10(this);
   1.403 +  return layer.forget();
   1.404 +}
   1.405 +
   1.406 +already_AddRefed<ContainerLayer>
   1.407 +LayerManagerD3D10::CreateContainerLayer()
   1.408 +{
   1.409 +  nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D10(this);
   1.410 +  return layer.forget();
   1.411 +}
   1.412 +
   1.413 +already_AddRefed<ImageLayer>
   1.414 +LayerManagerD3D10::CreateImageLayer()
   1.415 +{
   1.416 +  nsRefPtr<ImageLayer> layer = new ImageLayerD3D10(this);
   1.417 +  return layer.forget();
   1.418 +}
   1.419 +
   1.420 +already_AddRefed<ColorLayer>
   1.421 +LayerManagerD3D10::CreateColorLayer()
   1.422 +{
   1.423 +  nsRefPtr<ColorLayer> layer = new ColorLayerD3D10(this);
   1.424 +  return layer.forget();
   1.425 +}
   1.426 +
   1.427 +already_AddRefed<CanvasLayer>
   1.428 +LayerManagerD3D10::CreateCanvasLayer()
   1.429 +{
   1.430 +  nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D10(this);
   1.431 +  return layer.forget();
   1.432 +}
   1.433 +
   1.434 +already_AddRefed<ReadbackLayer>
   1.435 +LayerManagerD3D10::CreateReadbackLayer()
   1.436 +{
   1.437 +  nsRefPtr<ReadbackLayer> layer = new ReadbackLayerD3D10(this);
   1.438 +  return layer.forget();
   1.439 +}
   1.440 +
   1.441 +static void ReleaseTexture(void *texture)
   1.442 +{
   1.443 +  static_cast<ID3D10Texture2D*>(texture)->Release();
   1.444 +}
   1.445 +
   1.446 +TemporaryRef<DrawTarget>
   1.447 +LayerManagerD3D10::CreateOptimalDrawTarget(const IntSize &aSize,
   1.448 +                                           SurfaceFormat aFormat)
   1.449 +{
   1.450 +  if ((aFormat != SurfaceFormat::B8G8R8X8 &&
   1.451 +       aFormat != SurfaceFormat::B8G8R8A8)) {
   1.452 +    return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
   1.453 +  }
   1.454 +
   1.455 +  nsRefPtr<ID3D10Texture2D> texture;
   1.456 +  
   1.457 +  CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
   1.458 +  desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
   1.459 +  desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
   1.460 +  
   1.461 +  HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
   1.462 +
   1.463 +  if (FAILED(hr)) {
   1.464 +    NS_WARNING("Failed to create new texture for CreateOptimalDrawTarget!");
   1.465 +    return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
   1.466 +  }
   1.467 +
   1.468 +  RefPtr<DrawTarget> dt =
   1.469 +    Factory::CreateDrawTargetForD3D10Texture(texture, aFormat);
   1.470 +
   1.471 +  if (!dt) {
   1.472 +    return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
   1.473 +  }
   1.474 +
   1.475 +  return dt;
   1.476 +}
   1.477 +
   1.478 +
   1.479 +TemporaryRef<DrawTarget>
   1.480 +LayerManagerD3D10::CreateOptimalMaskDrawTarget(const IntSize &aSize)
   1.481 +{
   1.482 +  return CreateOptimalDrawTarget(aSize, SurfaceFormat::B8G8R8A8);
   1.483 +}
   1.484 +
   1.485 +
   1.486 +TemporaryRef<DrawTarget>
   1.487 +LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize,
   1.488 +                                    SurfaceFormat aFormat)
   1.489 +{
   1.490 +  if ((aFormat != SurfaceFormat::B8G8R8A8 &&
   1.491 +       aFormat != SurfaceFormat::B8G8R8X8) ||
   1.492 +       gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() != BackendType::DIRECT2D) {
   1.493 +    return LayerManager::CreateDrawTarget(aSize, aFormat);
   1.494 +  }
   1.495 +
   1.496 +  nsRefPtr<ID3D10Texture2D> texture;
   1.497 +  
   1.498 +  CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
   1.499 +  desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
   1.500 +  
   1.501 +  HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
   1.502 +
   1.503 +  if (FAILED(hr)) {
   1.504 +    NS_WARNING("Failed to create new texture for CreateOptimalDrawTarget!");
   1.505 +    return LayerManager::CreateDrawTarget(aSize, aFormat);
   1.506 +  }
   1.507 +
   1.508 +  RefPtr<DrawTarget> surface =
   1.509 +    Factory::CreateDrawTargetForD3D10Texture(texture, aFormat);
   1.510 +
   1.511 +  if (!surface) {
   1.512 +    return LayerManager::CreateDrawTarget(aSize, aFormat);
   1.513 +  }
   1.514 +  
   1.515 +  return surface;
   1.516 +}
   1.517 +
   1.518 +ReadbackManagerD3D10*
   1.519 +LayerManagerD3D10::readbackManager()
   1.520 +{
   1.521 +  EnsureReadbackManager();
   1.522 +  return mReadbackManager;
   1.523 +}
   1.524 +
   1.525 +void
   1.526 +LayerManagerD3D10::SetViewport(const nsIntSize &aViewport)
   1.527 +{
   1.528 +  mViewport = aViewport;
   1.529 +
   1.530 +  D3D10_VIEWPORT viewport;
   1.531 +  viewport.MaxDepth = 1.0f;
   1.532 +  viewport.MinDepth = 0;
   1.533 +  viewport.Width = aViewport.width;
   1.534 +  viewport.Height = aViewport.height;
   1.535 +  viewport.TopLeftX = 0;
   1.536 +  viewport.TopLeftY = 0;
   1.537 +
   1.538 +  mDevice->RSSetViewports(1, &viewport);
   1.539 +
   1.540 +  gfx3DMatrix projection;
   1.541 +  /*
   1.542 +   * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
   1.543 +   * <1.0, -1.0> bottomright)
   1.544 +   */
   1.545 +  projection._11 = 2.0f / aViewport.width;
   1.546 +  projection._22 = -2.0f / aViewport.height;
   1.547 +  projection._33 = 0.0f;
   1.548 +  projection._41 = -1.0f;
   1.549 +  projection._42 = 1.0f;
   1.550 +  projection._44 = 1.0f;
   1.551 +
   1.552 +  HRESULT hr = mEffect->GetVariableByName("mProjection")->
   1.553 +    SetRawValue(&projection._11, 0, 64);
   1.554 +
   1.555 +  if (FAILED(hr)) {
   1.556 +    NS_WARNING("Failed to set projection matrix.");
   1.557 +  }
   1.558 +}
   1.559 +
   1.560 +void
   1.561 +LayerManagerD3D10::SetupInputAssembler()
   1.562 +{
   1.563 +  mDevice->IASetInputLayout(mInputLayout);
   1.564 +
   1.565 +  UINT stride = sizeof(Vertex);
   1.566 +  UINT offset = 0;
   1.567 +  ID3D10Buffer *buffer = mVertexBuffer;
   1.568 +  mDevice->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
   1.569 +  mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
   1.570 +}
   1.571 +
   1.572 +void
   1.573 +LayerManagerD3D10::SetupPipeline()
   1.574 +{
   1.575 +  VerifyBufferSize();
   1.576 +  UpdateRenderTarget();
   1.577 +
   1.578 +  nsIntRect rect;
   1.579 +  mWidget->GetClientBounds(rect);
   1.580 +
   1.581 +  HRESULT hr;
   1.582 +
   1.583 +  hr = mEffect->GetVariableByName("vTextureCoords")->AsVector()->
   1.584 +    SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
   1.585 +
   1.586 +  if (FAILED(hr)) {
   1.587 +    NS_WARNING("Failed to set Texture Coordinates.");
   1.588 +    return;
   1.589 +  }
   1.590 +
   1.591 +  ID3D10RenderTargetView *view = mRTView;
   1.592 +  mDevice->OMSetRenderTargets(1, &view, nullptr);
   1.593 +
   1.594 +  SetupInputAssembler();
   1.595 +
   1.596 +  SetViewport(nsIntSize(rect.width, rect.height));
   1.597 +}
   1.598 +
   1.599 +void
   1.600 +LayerManagerD3D10::UpdateRenderTarget()
   1.601 +{
   1.602 +  if (mRTView || !mSwapChain) {
   1.603 +    return;
   1.604 +  }
   1.605 +
   1.606 +  HRESULT hr;
   1.607 +
   1.608 +  nsRefPtr<ID3D10Texture2D> backBuf;
   1.609 +  hr = mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
   1.610 +  if (FAILED(hr)) {
   1.611 +    return;
   1.612 +  }
   1.613 +  mDevice->CreateRenderTargetView(backBuf, nullptr, getter_AddRefs(mRTView));
   1.614 +}
   1.615 +
   1.616 +void
   1.617 +LayerManagerD3D10::VerifyBufferSize()
   1.618 +{
   1.619 +  nsIntRect rect;
   1.620 +  mWidget->GetClientBounds(rect);
   1.621 +
   1.622 +  if (mSwapChain) {
   1.623 +    DXGI_SWAP_CHAIN_DESC swapDesc;
   1.624 +    mSwapChain->GetDesc(&swapDesc);
   1.625 +
   1.626 +    if (swapDesc.BufferDesc.Width == rect.width &&
   1.627 +        swapDesc.BufferDesc.Height == rect.height) {
   1.628 +      return;
   1.629 +    }
   1.630 +
   1.631 +    mRTView = nullptr;
   1.632 +    if (IsRunningInWindowsMetro()) {
   1.633 +      mSwapChain->ResizeBuffers(2, rect.width, rect.height,
   1.634 +                                DXGI_FORMAT_B8G8R8A8_UNORM,
   1.635 +                                0);
   1.636 +      mDisableSequenceForNextFrame = true;
   1.637 +    } else if (gfxWindowsPlatform::IsOptimus()) {
   1.638 +      mSwapChain->ResizeBuffers(1, rect.width, rect.height,
   1.639 +                                DXGI_FORMAT_B8G8R8A8_UNORM,
   1.640 +                                0);
   1.641 +    } else {
   1.642 +      mSwapChain->ResizeBuffers(1, rect.width, rect.height,
   1.643 +                                DXGI_FORMAT_B8G8R8A8_UNORM,
   1.644 +                                DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
   1.645 +    }
   1.646 +  }
   1.647 +}
   1.648 +
   1.649 +void
   1.650 +LayerManagerD3D10::EnsureReadbackManager()
   1.651 +{
   1.652 +  if (mReadbackManager) {
   1.653 +    return;
   1.654 +  }
   1.655 +
   1.656 +  DeviceAttachments *attachments;
   1.657 +  UINT size = sizeof(DeviceAttachments*);
   1.658 +  if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) {
   1.659 +    // Strange! This shouldn't happen ... return a readback manager for this
   1.660 +    // layer manager only.
   1.661 +    mReadbackManager = new ReadbackManagerD3D10();
   1.662 +    gfx::LogFailure(NS_LITERAL_CSTRING("Couldn't get device attachments for device."));
   1.663 +    return;
   1.664 +  }
   1.665 +
   1.666 +  if (attachments->mReadbackManager) {
   1.667 +    mReadbackManager = attachments->mReadbackManager;
   1.668 +    return;
   1.669 +  }
   1.670 +
   1.671 +  mReadbackManager = new ReadbackManagerD3D10();
   1.672 +  attachments->mReadbackManager = mReadbackManager;
   1.673 +}
   1.674 +
   1.675 +void
   1.676 +LayerManagerD3D10::Render(EndTransactionFlags aFlags)
   1.677 +{
   1.678 +  static_cast<LayerD3D10*>(mRoot->ImplData())->Validate();
   1.679 +
   1.680 +  if (aFlags & END_NO_COMPOSITE) {
   1.681 +    return;
   1.682 +  }
   1.683 +
   1.684 +  SetupPipeline();
   1.685 +
   1.686 +  float black[] = { 0, 0, 0, 0 };
   1.687 +  device()->ClearRenderTargetView(mRTView, black);
   1.688 +
   1.689 +  nsIntRect rect;
   1.690 +  mWidget->GetClientBounds(rect);
   1.691 +
   1.692 +  const nsIntRect *clipRect = mRoot->GetClipRect();
   1.693 +  D3D10_RECT r;
   1.694 +  if (clipRect) {
   1.695 +    r.left = (LONG)clipRect->x;
   1.696 +    r.top = (LONG)clipRect->y;
   1.697 +    r.right = (LONG)(clipRect->x + clipRect->width);
   1.698 +    r.bottom = (LONG)(clipRect->y + clipRect->height);
   1.699 +  } else {
   1.700 +    r.left = r.top = 0;
   1.701 +    r.right = rect.width;
   1.702 +    r.bottom = rect.height;
   1.703 +  }
   1.704 +  device()->RSSetScissorRects(1, &r);
   1.705 +
   1.706 +  static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer();
   1.707 +
   1.708 +  if (!mRegionToClear.IsEmpty()) {
   1.709 +    float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
   1.710 +    gfx::Matrix4x4 transform;
   1.711 +    effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform, 0, 64);
   1.712 +    effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color);
   1.713 +
   1.714 +    ID3D10EffectTechnique *technique = effect()->GetTechniqueByName("RenderClearLayer");
   1.715 +
   1.716 +    nsIntRegionRectIterator iter(mRegionToClear);
   1.717 +    const nsIntRect *r;
   1.718 +    while ((r = iter.Next())) {
   1.719 +      effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
   1.720 +        ShaderConstantRectD3D10(
   1.721 +        (float)r->x,
   1.722 +        (float)r->y,
   1.723 +        (float)r->width,
   1.724 +        (float)r->height)
   1.725 +        );
   1.726 +
   1.727 +      technique->GetPassByIndex(0)->Apply(0);
   1.728 +      device()->Draw(4, 0);
   1.729 +    }
   1.730 +  }
   1.731 +
   1.732 +  // See bug 630197 - we have some reasons to believe if an earlier call
   1.733 +  // returned an error, the upcoming present call may raise an exception.
   1.734 +  // This will check if any of the calls done recently has returned an error
   1.735 +  // and bails on composition. On the -next- frame we will then abandon
   1.736 +  // hardware acceleration from gfxWindowsPlatform::VerifyD2DDevice.
   1.737 +  // This might not be the 'optimal' solution but it will help us assert
   1.738 +  // whether our thoughts of the causes of the issues are correct.
   1.739 +  if (FAILED(mDevice->GetDeviceRemovedReason())) {
   1.740 +    return;
   1.741 +  }
   1.742 +
   1.743 +  if (mTarget) {
   1.744 +    PaintToTarget();
   1.745 +  } else {
   1.746 +    mSwapChain->Present(0, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0);
   1.747 +    mDisableSequenceForNextFrame = false;
   1.748 +  }
   1.749 +  RecordFrame();
   1.750 +  PostPresent();
   1.751 +}
   1.752 +
   1.753 +void
   1.754 +LayerManagerD3D10::PaintToTarget()
   1.755 +{
   1.756 +  nsRefPtr<ID3D10Texture2D> backBuf;
   1.757 +  
   1.758 +  mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
   1.759 +
   1.760 +  D3D10_TEXTURE2D_DESC bbDesc;
   1.761 +  backBuf->GetDesc(&bbDesc);
   1.762 +
   1.763 +  CD3D10_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height);
   1.764 +  softDesc.MipLevels = 1;
   1.765 +  softDesc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
   1.766 +  softDesc.Usage = D3D10_USAGE_STAGING;
   1.767 +  softDesc.BindFlags = 0;
   1.768 +
   1.769 +  nsRefPtr<ID3D10Texture2D> readTexture;
   1.770 +
   1.771 +  HRESULT hr = device()->CreateTexture2D(&softDesc, nullptr, getter_AddRefs(readTexture));
   1.772 +  if (FAILED(hr)) {
   1.773 +    ReportFailure(NS_LITERAL_CSTRING("LayerManagerD3D10::PaintToTarget(): Failed to create texture"),
   1.774 +                  hr);
   1.775 +    return;
   1.776 +  }
   1.777 +
   1.778 +  device()->CopyResource(readTexture, backBuf);
   1.779 +
   1.780 +  D3D10_MAPPED_TEXTURE2D map;
   1.781 +  readTexture->Map(0, D3D10_MAP_READ, 0, &map);
   1.782 +
   1.783 +  nsRefPtr<gfxImageSurface> tmpSurface =
   1.784 +    new gfxImageSurface((unsigned char*)map.pData,
   1.785 +                        gfxIntSize(bbDesc.Width, bbDesc.Height),
   1.786 +                        map.RowPitch,
   1.787 +                        gfxImageFormat::ARGB32);
   1.788 +
   1.789 +  mTarget->SetSource(tmpSurface);
   1.790 +  mTarget->SetOperator(gfxContext::OPERATOR_OVER);
   1.791 +  mTarget->Paint();
   1.792 +
   1.793 +  readTexture->Unmap(0);
   1.794 +}
   1.795 +
   1.796 +void
   1.797 +LayerManagerD3D10::ReportFailure(const nsACString &aMsg, HRESULT aCode)
   1.798 +{
   1.799 +  // We could choose to abort here when hr == E_OUTOFMEMORY.
   1.800 +  nsCString msg;
   1.801 +  msg.Append(aMsg);
   1.802 +  msg.AppendLiteral(" Error code: ");
   1.803 +  msg.AppendInt(uint32_t(aCode));
   1.804 +  NS_WARNING(msg.BeginReading());
   1.805 +
   1.806 +  gfx::LogFailure(msg);
   1.807 +}
   1.808 +
   1.809 +LayerD3D10::LayerD3D10(LayerManagerD3D10 *aManager)
   1.810 +  : mD3DManager(aManager)
   1.811 +{
   1.812 +}
   1.813 +
   1.814 +ID3D10EffectTechnique*
   1.815 +LayerD3D10::SelectShader(uint8_t aFlags)
   1.816 +{
   1.817 +  switch (aFlags) {
   1.818 +  case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_LINEAR | SHADER_MASK):
   1.819 +    return effect()->GetTechniqueByName("RenderRGBALayerNonPremulMask");
   1.820 +  case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
   1.821 +    return effect()->GetTechniqueByName("RenderRGBALayerNonPremul");
   1.822 +  case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_POINT | SHADER_NO_MASK):
   1.823 +    return effect()->GetTechniqueByName("RenderRGBALayerNonPremulPoint");
   1.824 +  case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_POINT | SHADER_MASK):
   1.825 +    return effect()->GetTechniqueByName("RenderRGBALayerNonPremulPointMask");
   1.826 +  case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK_3D):
   1.827 +    return effect()->GetTechniqueByName("RenderRGBALayerPremulMask3D");
   1.828 +  case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK):
   1.829 +    return effect()->GetTechniqueByName("RenderRGBALayerPremulMask");
   1.830 +  case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
   1.831 +    return effect()->GetTechniqueByName("RenderRGBALayerPremul");
   1.832 +  case (SHADER_RGBA | SHADER_PREMUL | SHADER_POINT | SHADER_MASK):
   1.833 +    return effect()->GetTechniqueByName("RenderRGBALayerPremulPointMask");
   1.834 +  case (SHADER_RGBA | SHADER_PREMUL | SHADER_POINT | SHADER_NO_MASK):
   1.835 +    return effect()->GetTechniqueByName("RenderRGBALayerPremulPoint");
   1.836 +  case (SHADER_RGB | SHADER_PREMUL | SHADER_POINT | SHADER_MASK):
   1.837 +    return effect()->GetTechniqueByName("RenderRGBLayerPremulPointMask");
   1.838 +  case (SHADER_RGB | SHADER_PREMUL | SHADER_POINT | SHADER_NO_MASK):
   1.839 +    return effect()->GetTechniqueByName("RenderRGBLayerPremulPoint");
   1.840 +  case (SHADER_RGB | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK):
   1.841 +    return effect()->GetTechniqueByName("RenderRGBLayerPremulMask");
   1.842 +  case (SHADER_RGB | SHADER_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
   1.843 +    return effect()->GetTechniqueByName("RenderRGBLayerPremul");
   1.844 +  case (SHADER_SOLID | SHADER_MASK):
   1.845 +    return effect()->GetTechniqueByName("RenderSolidColorLayerMask");
   1.846 +  case (SHADER_SOLID | SHADER_NO_MASK):
   1.847 +    return effect()->GetTechniqueByName("RenderSolidColorLayer");
   1.848 +  case (SHADER_COMPONENT_ALPHA | SHADER_MASK):
   1.849 +    return effect()->GetTechniqueByName("RenderComponentAlphaLayerMask");
   1.850 +  case (SHADER_COMPONENT_ALPHA | SHADER_NO_MASK):
   1.851 +    return effect()->GetTechniqueByName("RenderComponentAlphaLayer");
   1.852 +  case (SHADER_YCBCR | SHADER_MASK):
   1.853 +    return effect()->GetTechniqueByName("RenderYCbCrLayerMask");
   1.854 +  case (SHADER_YCBCR | SHADER_NO_MASK):
   1.855 +    return effect()->GetTechniqueByName("RenderYCbCrLayer");
   1.856 +  default:
   1.857 +    NS_ERROR("Invalid shader.");
   1.858 +    return nullptr;
   1.859 +  }
   1.860 +}
   1.861 +
   1.862 +uint8_t
   1.863 +LayerD3D10::LoadMaskTexture()
   1.864 +{
   1.865 +  if (Layer* maskLayer = GetLayer()->GetMaskLayer()) {
   1.866 +    IntSize size;
   1.867 +    nsRefPtr<ID3D10ShaderResourceView> maskSRV =
   1.868 +      static_cast<LayerD3D10*>(maskLayer->ImplData())->GetAsTexture(&size);
   1.869 +  
   1.870 +    if (!maskSRV) {
   1.871 +      return SHADER_NO_MASK;
   1.872 +    }
   1.873 +
   1.874 +    Matrix maskTransform;
   1.875 +    Matrix4x4 effectiveTransform = maskLayer->GetEffectiveTransform();
   1.876 +    bool maskIs2D = effectiveTransform.CanDraw2D(&maskTransform);
   1.877 +    NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
   1.878 +    Rect bounds = Rect(Point(), Size(size));
   1.879 +    bounds = maskTransform.TransformBounds(bounds);
   1.880 +
   1.881 +    effect()->GetVariableByName("vMaskQuad")->AsVector()->SetFloatVector(
   1.882 +      ShaderConstantRectD3D10(
   1.883 +        (float)bounds.x,
   1.884 +        (float)bounds.y,
   1.885 +        (float)bounds.width,
   1.886 +        (float)bounds.height)
   1.887 +      );
   1.888 +
   1.889 +    effect()->GetVariableByName("tMask")->AsShaderResource()->SetResource(maskSRV);
   1.890 +    return SHADER_MASK;
   1.891 +  }
   1.892 +
   1.893 +  return SHADER_NO_MASK;
   1.894 +}
   1.895 +
   1.896 +}
   1.897 +}

mercurial