tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

composite.cpp (5736B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifdef _WIN32
      6 
      7 #  include <d3d11.h>
      8 #  include <wrl/client.h>
      9 #  include <dcomp.h>
     10 #  include <assert.h>
     11 #  include <dxgi.h>
     12 
     13 #  include <stdio.h>
     14 
     15 using namespace Microsoft::WRL;
     16 
     17 // A basic composition layer backed by a swap-chain for DirectComposition
     18 class Layer {
     19 public:
     20  Layer(int width, int height, bool is_opaque,
     21        const ComPtr<IDXGIFactory2>& dxgiFactory,
     22        const ComPtr<ID3D11Device>& d3dDevice,
     23        const ComPtr<IDCompositionDesktopDevice>& dCompDevice) {
     24    HRESULT hr;
     25 
     26    DXGI_SWAP_CHAIN_DESC1 desc{};
     27    desc.Width = width;
     28    desc.Height = height;
     29    desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
     30    desc.SampleDesc.Count = 1;
     31    desc.SampleDesc.Quality = 0;
     32    desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
     33    desc.BufferCount = 2;
     34    // DXGI_SCALING_NONE caused swap chain creation failure.
     35    desc.Scaling = DXGI_SCALING_STRETCH;
     36    desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
     37    desc.AlphaMode =
     38        is_opaque ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED;
     39    desc.Flags = 0;
     40 
     41    // Create a swap-chain, visual, attach them and get the backbuffer texture
     42    // to draw to
     43 
     44    hr = dxgiFactory->CreateSwapChainForComposition(
     45        d3dDevice.Get(), &desc, nullptr, mSwapChain.GetAddressOf());
     46    assert(SUCCEEDED(hr));
     47 
     48    hr = dCompDevice->CreateVisual(mVisual.GetAddressOf());
     49    assert(SUCCEEDED(hr));
     50 
     51    mVisual->SetContent(mSwapChain.Get());
     52 
     53    hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
     54                               (void**)mBackBuffer.GetAddressOf());
     55    assert(SUCCEEDED(hr));
     56  }
     57 
     58  ComPtr<IDXGISwapChain1> mSwapChain;
     59  ComPtr<IDCompositionVisual2> mVisual;
     60  ComPtr<ID3D11Texture2D> mBackBuffer;
     61 };
     62 
     63 // A basic DirectComposition compositor implementation
     64 class Compositor {
     65 public:
     66  Compositor(ID3D11Device* aDevice, HWND hWnd) : pD3DDevice(aDevice) {
     67    HRESULT hr;
     68 
     69    // Get DXGI device from D3D (which was created by ANGLE)
     70    hr = pD3DDevice.As(&pDXGIDevice);
     71    assert(SUCCEEDED(hr));
     72 
     73    // Create DirectComposition
     74    hr = DCompositionCreateDevice2(pDXGIDevice.Get(),
     75                                   __uuidof(IDCompositionDesktopDevice),
     76                                   (void**)pDCompDevice.GetAddressOf());
     77    assert(SUCCEEDED(hr));
     78 
     79    // Bind DC to the hWnd that was created by winit
     80    hr = pDCompDevice->CreateTargetForHwnd(hWnd, TRUE,
     81                                           pCompositionTarget.GetAddressOf());
     82    assert(SUCCEEDED(hr));
     83 
     84    // Create and set root of the visual tree
     85    hr = pDCompDevice->CreateVisual(pRootVisual.GetAddressOf());
     86    assert(SUCCEEDED(hr));
     87    hr = pCompositionTarget->SetRoot(pRootVisual.Get());
     88    assert(SUCCEEDED(hr));
     89    pRootVisual->SetBitmapInterpolationMode(
     90        DCOMPOSITION_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
     91 
     92    // Enable DC debug counter overlay (helpful for seeing if DC composition is
     93    // active during development)
     94    hr = pDCompDevice.As(&pDCompDebug);
     95    assert(SUCCEEDED(hr));
     96    pDCompDebug->EnableDebugCounters();
     97 
     98    // Get a DXGI factory interface for creating swap-chains
     99    hr = pDXGIDevice->GetAdapter(&pDXGIAdapter);
    100    assert(SUCCEEDED(hr));
    101    hr = pDXGIAdapter->GetParent(__uuidof(IDXGIFactory2),
    102                                 (void**)pIDXGIFactory.GetAddressOf());
    103    assert(SUCCEEDED(hr));
    104  }
    105 
    106  ~Compositor() {}
    107 
    108  // Construct a layer of given dimensions.
    109  Layer* create_layer(int width, int height, bool is_opaque) {
    110    Layer* layer = new Layer(width, height, is_opaque, pIDXGIFactory,
    111                             pD3DDevice, pDCompDevice);
    112 
    113    return layer;
    114  }
    115 
    116  void begin_frame() { pRootVisual->RemoveAllVisuals(); }
    117 
    118  void add_layer(Layer* layer) {
    119    // TODO(gwc): Don't add the visual during creation. Once we support multiple
    120    // swap-chain layers, we'll need to support rebuilding the visual tree for
    121    // DC as needed.
    122    HRESULT hr = pRootVisual->AddVisual(layer->mVisual.Get(), FALSE, nullptr);
    123    assert(SUCCEEDED(hr));
    124  }
    125 
    126  void end_frame() {
    127    // TODO(gwc): Only commit if the visual tree was rebuilt
    128    pDCompDevice->Commit();
    129  }
    130 
    131 private:
    132  ComPtr<ID3D11Device> pD3DDevice;
    133  ComPtr<IDXGIDevice> pDXGIDevice;
    134  ComPtr<IDCompositionDesktopDevice> pDCompDevice;
    135  ComPtr<IDCompositionTarget> pCompositionTarget;
    136  ComPtr<IDCompositionVisual2> pRootVisual;
    137  ComPtr<IDCompositionDeviceDebug> pDCompDebug;
    138  ComPtr<IDXGIAdapter> pDXGIAdapter;
    139  ComPtr<IDXGIFactory2> pIDXGIFactory;
    140 };
    141 
    142 // Bindings called by wrench rust impl of the LayerCompositor trait
    143 extern "C" {
    144 Compositor* wrc_new(void* d3d11_device, void* hwnd) {
    145  return new Compositor(static_cast<ID3D11Device*>(d3d11_device),
    146                        static_cast<HWND>(hwnd));
    147 }
    148 
    149 void wrc_delete(Compositor* compositor) { delete compositor; }
    150 
    151 Layer* wrc_create_layer(Compositor* compositor, int width, int height,
    152                        bool is_opaque) {
    153  return compositor->create_layer(width, height, is_opaque);
    154 }
    155 
    156 void* wrc_get_layer_backbuffer(Layer* layer) {
    157  void* p = layer->mBackBuffer.Get();
    158  return p;
    159 }
    160 
    161 void wrc_present_layer(Layer* layer) { layer->mSwapChain->Present(0, 0); }
    162 
    163 void wrc_begin_frame(Compositor* compositor) { compositor->begin_frame(); }
    164 
    165 void wrc_end_frame(Compositor* compositor) { compositor->end_frame(); }
    166 
    167 void wrc_add_layer(Compositor* compositor, Layer* layer) {
    168  compositor->add_layer(layer);
    169 }
    170 
    171 void wrc_set_layer_position(Layer* layer, float x, float y) {
    172  layer->mVisual->SetOffsetX(x);
    173  layer->mVisual->SetOffsetY(y);
    174 }
    175 }
    176 
    177 #endif