[FTW] Use DirectX SharedResource as basis for SharedBitmap
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Aug 2019 18:20:22 +0000 (18:20 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Aug 2019 18:20:22 +0000 (18:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=201157

Reviewed by Alex Christensen.

Source/WebCore:

Currently an ID2D1Bitmap is used as the backing store for the SharedBitmap that is the
base type for sharing data between the WebContent Process and the UIProcess. However, this
involves moving GPU memory to local memory, copying that memory into the SharedMemory member
of the SharedBitmap, then building a new GPU bitmap on the UIProcess side from that SharedMemory.

Profiling indicates that this is the single largest place FTW WebKit spends its time.

Instead, we should use Direct2D's ability to render to an IDXGISurface, which can be shared
between multiple processes. This should avoid the GPU->CPU copy, the Direct2D-allocated
CPU->Shared Memory copy, and the shared memory to GPU copy.

* platform/graphics/win/BackingStoreBackendDirect2D.h:
(WebCore::BackingStoreBackendDirect2D::renderTarget const): Change type.
(WebCore::BackingStoreBackendDirect2D::dxSurface const): Added.
(WebCore::BackingStoreBackendDirect2D::BackingStoreBackendDirect2D): Require a DXD11 device.
* platform/graphics/win/BackingStoreBackendDirect2DImpl.cpp:
(WebCore::BackingStoreBackendDirect2DImpl::BackingStoreBackendDirect2DImpl): Use Direct2D's
IDXGISurface to make a render target we can use to support our fast cross-process sharing.
(WebCore::BackingStoreBackendDirect2DImpl::scroll):
* platform/graphics/win/BackingStoreBackendDirect2DImpl.h:
* platform/graphics/win/Direct2DOperations.cpp:
(WebCore::Direct2D::fillRect): Remove unneeded PlatformContextStateSaver.
(WebCore::Direct2D::fillRoundedRect): Ditto.
(WebCore::Direct2D::fillRectWithGradient): Ditto.
(WebCore::Direct2D::fillPath): Ditto.
(WebCore::Direct2D::strokePath): Ditto.
* platform/graphics/win/Direct2DUtilities.cpp:
(WebCore::Direct2D::pixelFormat): Switch to constants for bitmap format.
(WebCore::Direct2D::createDXGISurfaceOfSize): Added.
(WebCore::Direct2D::createSurfaceRenderTarget): Added.
(WebCore::Direct2D::writeDiagnosticPNGToPath):
(WebCore::Direct2D::dxgiImmediateContext): Added.
(WebCore::Direct2D::defaultDirectXDevice): Added.
(WebCore::Direct2D::createDeviceAndContext): Added.
(WebCore::Direct2D::toDXGIDevice): Added.
(WebCore::Direct2D::factoryForDXGIDevice): Added.
* platform/graphics/win/Direct2DUtilities.h:

Source/WebKit:

Currently an ID2D1Bitmap is used as the backing store for the SharedBitmap that is the
base type for sharing data between the WebContent Process and the UIProcess. However, this
involves moving GPU memory to local memory, copying that memory into the SharedMemory member
of the SharedBitmap, then building a new GPU bitmap on the UIProcess side from that SharedMemory.

Profiling indicates that this is the single largest place FTW WebKit spends its time.

Instead, we should use Direct2D's ability to render to an IDXGISurface, which can be shared
between multiple processes. This should avoid the GPU->CPU copy, the Direct2D-allocated
CPU->Shared Memory copy, and the shared memory to GPU copy.

Reviewed by Alex Christensen.

* Platform/SharedMemory.h:
* Platform/win/SharedMemoryWin.cpp:
(WebKit::SharedMemory::Handle::encodeHandle): Added.
(WebKit::SharedMemory::Handle::encode const): Use new helper function.
(WebKit::SharedMemory::Handle::decodeHandle): Added.
(WebKit::SharedMemory::Handle::decode): Use new helper function.
* PlatformFTW.cmake: Add D3X11 libraries.
* Shared/ShareableBitmap.cpp:
(WebKit::ShareableBitmap::Configuration::encode const): Encode shared resource handle for DX texture.
(WebKit::ShareableBitmap::Configuration::decode): Ditto (but decode).
(WebKit::ShareableBitmap::ShareableBitmap): Create SharedResource (if needed).
(WebKit::ShareableBitmap::~ShareableBitmap): Add cleanup code for SharedResoure.
(WebKit::ShareableBitmap::numBytesForSize): Only allocate a small memory store when using GPU textures.
* Shared/ShareableBitmap.h:
(WebKit::ShareableBitmap::dxSurface):
* Shared/win/ShareableBitmapDirect2D.cpp:
(WebKit::ShareableBitmap::createSharedResource): Added.
(WebKit::ShareableBitmap::disposeSharedResource): Added.
(WebKit::ShareableBitmap::leakSharedResource): Added.
(WebKit::ShareableBitmap::createGraphicsContext): Update for new data types.
(WebKit::ShareableBitmap::paint): Ditto.
(WebKit::ShareableBitmap::createDirect2DSurface): Update for new data types.
(WebKit::ShareableBitmap::createImage): Ditto.
(WebKit::createSurfaceFromData): Deleted.
(WebKit::ShareableBitmap::sync): Deleted.
* UIProcess/BackingStore.cpp:
* UIProcess/BackingStore.h:
* UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp:
* UIProcess/WebPageProxy.cpp:
* UIProcess/WebPageProxy.h:
* UIProcess/win/BackingStoreDirect2D.cpp:
(WebKit::BackingStore::createBackend):
(WebKit::BackingStore::paint):
(WebKit::BackingStore::incorporateUpdate):
* UIProcess/win/PageClientImpl.cpp:
* UIProcess/win/WebPageProxyWin.cpp:
(WebKit::WebPageProxy::device const):
(WebKit::WebPageProxy::setDevice):
* UIProcess/win/WebView.cpp:
(WebKit::WebView::WebView): Initialize DirectX stuff.
(WebKit::WebView::paint): Use new DiretX drawing logic.
(WebKit::WebView::onSizeEvent): Update SwapChain's buffer sizes when resizing.
(WebKit::WebView::setupSwapChain): Added.
(WebKit::WebView::configureBackingStore): Added.
* UIProcess/win/WebView.h:
(WebKit::WebView::d3dDevice):
* WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:
(WebKit::DrawingAreaCoordinatedGraphics::display):

Source/WebKitLegacy:

* PlatformFTW.cmake: Link to DirectX to avoid build failure.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249335 268f45cc-cd09-0410-ab3c-d52691b4dbfc

33 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/win/BackingStoreBackendDirect2D.h
Source/WebCore/platform/graphics/win/BackingStoreBackendDirect2DImpl.cpp
Source/WebCore/platform/graphics/win/BackingStoreBackendDirect2DImpl.h
Source/WebCore/platform/graphics/win/Direct2DOperations.cpp
Source/WebCore/platform/graphics/win/Direct2DOperations.h
Source/WebCore/platform/graphics/win/Direct2DUtilities.cpp
Source/WebCore/platform/graphics/win/Direct2DUtilities.h
Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp
Source/WebCore/platform/graphics/win/GraphicsContextImplDirect2D.cpp
Source/WebCore/platform/graphics/win/ImageBufferDirect2D.cpp
Source/WebCore/platform/graphics/win/ImageDirect2D.cpp
Source/WebCore/svg/graphics/SVGImage.cpp
Source/WebKit/ChangeLog
Source/WebKit/Platform/SharedMemory.h
Source/WebKit/Platform/win/SharedMemoryWin.cpp
Source/WebKit/PlatformFTW.cmake
Source/WebKit/Shared/ShareableBitmap.cpp
Source/WebKit/Shared/ShareableBitmap.h
Source/WebKit/Shared/win/ShareableBitmapDirect2D.cpp
Source/WebKit/UIProcess/BackingStore.cpp
Source/WebKit/UIProcess/BackingStore.h
Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/win/BackingStoreDirect2D.cpp
Source/WebKit/UIProcess/win/PageClientImpl.cpp
Source/WebKit/UIProcess/win/WebPageProxyWin.cpp
Source/WebKit/UIProcess/win/WebView.cpp
Source/WebKit/UIProcess/win/WebView.h
Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
Source/WebKitLegacy/ChangeLog
Source/WebKitLegacy/PlatformFTW.cmake

index c71f0a0..29b7e32 100644 (file)
@@ -1,3 +1,48 @@
+2019-08-30  Brent Fulgham  <bfulgham@apple.com>
+
+        [FTW] Use DirectX SharedResource as basis for SharedBitmap
+        https://bugs.webkit.org/show_bug.cgi?id=201157
+
+        Reviewed by Alex Christensen.
+
+        Currently an ID2D1Bitmap is used as the backing store for the SharedBitmap that is the
+        base type for sharing data between the WebContent Process and the UIProcess. However, this
+        involves moving GPU memory to local memory, copying that memory into the SharedMemory member
+        of the SharedBitmap, then building a new GPU bitmap on the UIProcess side from that SharedMemory.
+
+        Profiling indicates that this is the single largest place FTW WebKit spends its time.
+
+        Instead, we should use Direct2D's ability to render to an IDXGISurface, which can be shared
+        between multiple processes. This should avoid the GPU->CPU copy, the Direct2D-allocated
+        CPU->Shared Memory copy, and the shared memory to GPU copy.
+        * platform/graphics/win/BackingStoreBackendDirect2D.h:
+        (WebCore::BackingStoreBackendDirect2D::renderTarget const): Change type.
+        (WebCore::BackingStoreBackendDirect2D::dxSurface const): Added.
+        (WebCore::BackingStoreBackendDirect2D::BackingStoreBackendDirect2D): Require a DXD11 device.
+        * platform/graphics/win/BackingStoreBackendDirect2DImpl.cpp:
+        (WebCore::BackingStoreBackendDirect2DImpl::BackingStoreBackendDirect2DImpl): Use Direct2D's
+        IDXGISurface to make a render target we can use to support our fast cross-process sharing.
+        (WebCore::BackingStoreBackendDirect2DImpl::scroll):
+        * platform/graphics/win/BackingStoreBackendDirect2DImpl.h:
+        * platform/graphics/win/Direct2DOperations.cpp:
+        (WebCore::Direct2D::fillRect): Remove unneeded PlatformContextStateSaver.
+        (WebCore::Direct2D::fillRoundedRect): Ditto.
+        (WebCore::Direct2D::fillRectWithGradient): Ditto.
+        (WebCore::Direct2D::fillPath): Ditto.
+        (WebCore::Direct2D::strokePath): Ditto.
+        * platform/graphics/win/Direct2DUtilities.cpp:
+        (WebCore::Direct2D::pixelFormat): Switch to constants for bitmap format.
+        (WebCore::Direct2D::createDXGISurfaceOfSize): Added.
+        (WebCore::Direct2D::createSurfaceRenderTarget): Added.
+        (WebCore::Direct2D::writeDiagnosticPNGToPath):
+        (WebCore::Direct2D::dxgiImmediateContext): Added.
+        (WebCore::Direct2D::defaultDirectXDevice): Added.
+        (WebCore::Direct2D::createDeviceAndContext): Added.
+        (WebCore::Direct2D::toDXGIDevice): Added.
+        (WebCore::Direct2D::factoryForDXGIDevice): Added.
+        * platform/graphics/win/Direct2DUtilities.h:
+
 2019-08-30  Sihui Liu  <sihui_liu@apple.com>
 
         IndexedDB: update size of database when database operation is completed
index a79df72..4832e7a 100644 (file)
@@ -34,7 +34,9 @@
 
 interface ID2D1Bitmap;
 interface ID2D1BitmapBrush;
-interface ID2D1DCRenderTarget;
+interface ID2D1RenderTarget;
+interface ID3D11Device1;
+interface IDXGISurface1;
 
 namespace WebCore {
 
@@ -44,20 +46,24 @@ class BackingStoreBackendDirect2D {
 public:
     virtual ~BackingStoreBackendDirect2D() = default;
 
-    ID2D1DCRenderTarget* renderTarget() const { return m_renderTarget.get(); }
+    ID2D1RenderTarget* renderTarget() const { return m_renderTarget.get(); }
     ID2D1Bitmap* surface() const { return m_surface.get(); }
+    IDXGISurface1* dxSurface() const { return m_dxSurface.get(); }
     const IntSize& size() const { return m_size; }
 
     virtual void scroll(const IntRect& scrollRect, const IntSize& scrollOffset) = 0;
     virtual ID2D1BitmapBrush* bitmapBrush() = 0;
 
 protected:
-    BackingStoreBackendDirect2D(const IntSize& size)
-        : m_size(size)
+    BackingStoreBackendDirect2D(const IntSize& size, ID3D11Device1* device)
+        : m_device(device)
+        , m_size(size)
     {
     }
 
-    COMPtr<ID2D1DCRenderTarget> m_renderTarget;
+    COMPtr<ID3D11Device1> m_device;
+    COMPtr<ID2D1RenderTarget> m_renderTarget;
+    COMPtr<IDXGISurface1> m_dxSurface;
     COMPtr<ID2D1Bitmap> m_surface;
     IntSize m_size;
 };
index 92f2a8f..b4036c7 100644 (file)
 #include "ImageDecoderDirect2D.h"
 #include "IntRect.h"
 #include "IntSize.h"
+#include <d3d11_1.h>
 #include <wincodec.h>
 
 namespace WebCore {
 
 static const Seconds scrollHysteresisDuration { 300_ms };
 
-BackingStoreBackendDirect2DImpl::BackingStoreBackendDirect2DImpl(const IntSize& size, float deviceScaleFactor)
-    : BackingStoreBackendDirect2D(size)
+BackingStoreBackendDirect2DImpl::BackingStoreBackendDirect2DImpl(const IntSize& size, float deviceScaleFactor, ID3D11Device1* device)
+    : BackingStoreBackendDirect2D(size, device)
     , m_scrolledHysteresis([this](PAL::HysteresisState state) {
         if (state == PAL::HysteresisState::Stopped)
             m_scrollSurface = nullptr;
         }, scrollHysteresisDuration)
 {
-    m_renderTarget = WebCore::Direct2D::createGDIRenderTarget();
-
     IntSize scaledSize = m_size;
     scaledSize.scale(deviceScaleFactor);
-    m_surface = Direct2D::createBitmap(m_renderTarget.get(), scaledSize);
+
+    m_dxSurface = WebCore::Direct2D::createDXGISurfaceOfSize(scaledSize, m_device.get(), false);
+    m_renderTarget = WebCore::Direct2D::createSurfaceRenderTarget(m_dxSurface.get());
+
+    auto bitmapProperties = Direct2D::bitmapProperties();
+    HRESULT hr = m_renderTarget->CreateSharedBitmap(__uuidof(IDXGISurface1), reinterpret_cast<void*>(m_dxSurface.get()), &bitmapProperties, &m_surface);
+    RELEASE_ASSERT(SUCCEEDED(hr));
 }
 
 BackingStoreBackendDirect2DImpl::~BackingStoreBackendDirect2DImpl()
@@ -70,7 +75,12 @@ void BackingStoreBackendDirect2DImpl::scroll(const IntRect& scrollRect, const In
         ASSERT(m_size.height() >= scrollRect.size().height());
 #endif
         m_scrollSurfaceSize = sourceRect.size();
-        m_scrollSurface = Direct2D::createBitmap(m_renderTarget.get(), m_scrollSurfaceSize);
+        m_dxScrollSurface = WebCore::Direct2D::createDXGISurfaceOfSize(m_scrollSurfaceSize, m_device.get(), false);
+
+        m_scrollSurface = nullptr;
+        auto bitmapProperties = Direct2D::bitmapProperties();
+        HRESULT hr = m_renderTarget->CreateSharedBitmap(__uuidof(IDXGISurface1), reinterpret_cast<void*>(m_dxScrollSurface.get()), &bitmapProperties, &m_scrollSurface);
+        RELEASE_ASSERT(SUCCEEDED(hr));
     }
 
     auto sourceRectLocation = IntSize(sourceRect.x(), sourceRect.y());
index 11df9a8..51f77b9 100644 (file)
@@ -31,7 +31,7 @@
 #include <pal/HysteresisActivity.h>
 
 interface ID2D1BitmapBrush;
-interface IWICBitmap;
+interface IDXGISurface1;
 
 namespace WebCore {
 
@@ -39,7 +39,7 @@ class IntSize;
 
 class BackingStoreBackendDirect2DImpl final : public BackingStoreBackendDirect2D {
 public:
-    WEBCORE_EXPORT BackingStoreBackendDirect2DImpl(const IntSize&, float deviceScaleFactor);
+    WEBCORE_EXPORT BackingStoreBackendDirect2DImpl(const IntSize&, float deviceScaleFactor, ID3D11Device1*);
     virtual ~BackingStoreBackendDirect2DImpl();
 
 private:
@@ -48,6 +48,7 @@ private:
 
     IntSize m_scrollSurfaceSize;
     COMPtr<ID2D1Bitmap> m_scrollSurface;
+    COMPtr<IDXGISurface1> m_dxScrollSurface;
     COMPtr<ID2D1BitmapBrush> m_bitmapBrush;
 
     PAL::HysteresisActivity m_scrolledHysteresis;
index cc9f9d1..652d8a7 100644 (file)
@@ -406,7 +406,6 @@ void fillRect(PlatformContextDirect2D& platformContext, const FloatRect& rect, c
     auto context = platformContext.renderTarget();
 
     context->SetTags(1, __LINE__);
-    PlatformContextStateSaver stateSaver(platformContext);
     Function<void(ID2D1RenderTarget*)> drawFunction = [&platformContext, rect, &fillSource](ID2D1RenderTarget* renderTarget) {
         const D2D1_RECT_F d2dRect = rect;
         renderTarget->FillRectangle(&d2dRect, fillSource.brush.get());
@@ -423,7 +422,6 @@ void fillRect(PlatformContextDirect2D& platformContext, const FloatRect& rect, c
     auto context = platformContext.renderTarget();
 
     context->SetTags(1, __LINE__);
-    PlatformContextStateSaver stateSaver(platformContext);
     Function<void(ID2D1RenderTarget*)> drawFunction = [&platformContext, color, rect](ID2D1RenderTarget* renderTarget) {
         const D2D1_RECT_F d2dRect = rect;
         renderTarget->FillRectangle(&d2dRect, platformContext.brushWithColor(color).get());
@@ -446,7 +444,6 @@ void fillRoundedRect(PlatformContextDirect2D& platformContext, const FloatRounde
     bool equalHeights = (radii.topLeft().height() == radii.bottomLeft().height() && radii.bottomLeft().height() == radii.topRight().height() && radii.topRight().height() == radii.bottomRight().height());
     bool hasCustomFill = false; // FIXME: Why isn't a FillSource passed to this function?
     if (!hasCustomFill && equalWidths && equalHeights && radii.topLeft().width() * 2 == r.width() && radii.topLeft().height() * 2 == r.height()) {
-        PlatformContextStateSaver stateSaver(platformContext);
         Function<void(ID2D1RenderTarget*)> drawFunction = [&platformContext, color, rect, radii, r](ID2D1RenderTarget* renderTarget) {
             auto roundedRect = D2D1::RoundedRect(r, radii.topLeft().width(), radii.topLeft().height());
             renderTarget->FillRoundedRectangle(&roundedRect, platformContext.brushWithColor(color).get());
@@ -457,7 +454,6 @@ void fillRoundedRect(PlatformContextDirect2D& platformContext, const FloatRounde
         else
             drawWithoutShadow(platformContext, r, drawFunction);
     } else {
-        PlatformContextStateSaver stateSaver(platformContext);
         Path path;
         path.addRoundedRect(rect);
         fillPath(platformContext, path, color, shadowState);
@@ -489,7 +485,6 @@ void fillRectWithGradient(PlatformContextDirect2D& platformContext, const FloatR
     auto context = platformContext.renderTarget();
 
     context->SetTags(1, __LINE__);
-    PlatformContextStateSaver stateSaver(platformContext);
     Function<void(ID2D1RenderTarget*)> drawFunction = [&platformContext, rect, &gradient](ID2D1RenderTarget* renderTarget) {
         const D2D1_RECT_F d2dRect = rect;
         renderTarget->FillRectangle(&d2dRect, gradient);
@@ -506,8 +501,6 @@ void fillPath(PlatformContextDirect2D& platformContext, const Path& path, const
         path.activePath()->Close();
     }
 
-    PlatformContextStateSaver stateSaver(platformContext);
-
     auto context = platformContext.renderTarget();
 
     context->SetTags(1, __LINE__);
@@ -574,7 +567,6 @@ void strokePath(PlatformContextDirect2D& platformContext, const Path& path, cons
     
     context->SetTags(1, __LINE__);
 
-    PlatformContextStateSaver stateSaver(platformContext);
     auto boundingRect = path.fastBoundingRect();
     Function<void(ID2D1RenderTarget*)> drawFunction = [&platformContext, &path, &strokeSource](ID2D1RenderTarget* renderTarget) {
         renderTarget->DrawGeometry(path.platformPath(), strokeSource.brush.get(), strokeSource.thickness, platformContext.strokeStyle());
@@ -766,7 +758,7 @@ void drawNativeImage(PlatformContextDirect2D& platformContext, ID2D1Bitmap* imag
 {
     auto bitmapSize = image->GetSize();
 
-    float currHeight = orientation.usesWidthAsHeight() ? bitmapSize.width : bitmapSize.height;
+    float currHeight = options.orientation().usesWidthAsHeight() ? bitmapSize.width : bitmapSize.height;
     if (currHeight <= srcRect.y())
         return;
 
index 50d0efd..30f6025 100644 (file)
@@ -128,8 +128,8 @@ void clearRect(PlatformContextDirect2D&, const FloatRect&);
 
 void drawGlyphs(PlatformContextDirect2D&, const FillSource&, const StrokeSource&, const ShadowState&, const FloatPoint&, const Font&, double, const Vector<unsigned short>& glyphs, const Vector<float>& horizontalAdvances, const Vector<DWRITE_GLYPH_OFFSET>&, float, TextDrawingModeFlags, float, const FloatSize&, const Color&);
 
-void drawNativeImage(PlatformContextDirect2D&, IWICBitmap*, const FloatSize& imageSize, const FloatRect&, const FloatRect&, CompositeOperator, BlendMode, ImageOrientation, InterpolationQuality, float, const ShadowState&);
-void drawNativeImage(PlatformContextDirect2D&, ID2D1Bitmap*, const FloatSize& imageSize, const FloatRect&, const FloatRect&, CompositeOperator, BlendMode, ImageOrientation, InterpolationQuality, float, const ShadowState&);
+void drawNativeImage(PlatformContextDirect2D&, IWICBitmap*, const FloatSize& imageSize, const FloatRect&, const FloatRect&, const ImagePaintingOptions& options, float, const ShadowState&);
+void drawNativeImage(PlatformContextDirect2D&, ID2D1Bitmap*, const FloatSize& imageSize, const FloatRect&, const FloatRect&, const ImagePaintingOptions& options, float, const ShadowState&);
 void drawPath(PlatformContextDirect2D&, const Path&, const StrokeSource&, const ShadowState&);
 void drawPattern(PlatformContextDirect2D&, COMPtr<ID2D1Bitmap>&&, const IntSize&, const FloatRect&, const FloatRect&, const AffineTransform&, const FloatPoint&, CompositeOperator, BlendMode);
 
index 80031ea..5cadf89 100644 (file)
@@ -38,6 +38,7 @@
 #include "IntRect.h"
 #include "IntSize.h"
 #include <d2d1_1.h>
+#include <d3d11_1.h>
 #include <shlwapi.h>
 #include <wincodec.h>
 
@@ -46,6 +47,9 @@ namespace WebCore {
 
 namespace Direct2D {
 
+constexpr DXGI_FORMAT webkitTextureFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
+constexpr D2D1_ALPHA_MODE webkitAlphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
+
 IntSize bitmapSize(IWICBitmapSource* bitmapSource)
 {
     UINT width, height;
@@ -140,7 +144,7 @@ D2D1_PIXEL_FORMAT pixelFormatForSoftwareManipulation()
 D2D1_PIXEL_FORMAT pixelFormat()
 {
     // Since we need to interact with HDC from time-to-time, we are forced to use DXGI_FORMAT_B8G8R8A8_UNORM and D2D1_ALPHA_MODE_PREMULTIPLIED
-    return D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
+    return D2D1::PixelFormat(webkitTextureFormat, webkitAlphaMode);
 }
 
 GUID wicBitmapFormat()
@@ -228,6 +232,53 @@ COMPtr<ID2D1BitmapRenderTarget> createBitmapRenderTargetOfSize(const IntSize& si
     return bitmapContext;
 }
 
+COMPtr<IDXGISurface1> createDXGISurfaceOfSize(const IntSize& size, ID3D11Device1* directXDevice, bool crossProcess)
+{
+    if (!directXDevice)
+        directXDevice = Direct2D::defaultDirectXDevice();
+
+    // Create the render target texture
+    D3D11_TEXTURE2D_DESC desc;
+    ZeroMemory(&desc, sizeof(desc));
+    desc.Width = size.width();
+    desc.Height = size.height();
+    desc.MipLevels = 1;
+    desc.ArraySize = 1;
+    desc.Format = webkitTextureFormat;
+    desc.SampleDesc.Count = 1;
+    desc.Usage = D3D11_USAGE_DEFAULT;
+    desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+    desc.CPUAccessFlags = 0;
+    desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
+    if (crossProcess)
+        desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
+
+    COMPtr<ID3D11Texture2D> texture;
+    HRESULT hr = directXDevice->CreateTexture2D(&desc, nullptr, &texture);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    COMPtr<IDXGISurface1> surface;
+    hr = texture->QueryInterface(&surface);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    return surface;
+}
+
+COMPtr<ID2D1RenderTarget> createSurfaceRenderTarget(IDXGISurface1* surface)
+{
+    auto pixelFormat = D2D1::PixelFormat(webkitTextureFormat, webkitAlphaMode);
+
+    auto properties = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
+        pixelFormat, 0, 0, D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE, D2D1_FEATURE_LEVEL_10);
+
+    COMPtr<ID2D1RenderTarget> renderTarget;
+    HRESULT hr = GraphicsContext::systemFactory()->CreateDxgiSurfaceRenderTarget(surface, properties, &renderTarget);
+    if (!SUCCEEDED(hr))
+        return nullptr;
+
+    return renderTarget;
+}
+
 void copyRectFromOneSurfaceToAnother(ID2D1Bitmap* from, ID2D1Bitmap* to, const IntSize& sourceOffset, const IntRect& rect, const IntSize& destOffset)
 {
     IntSize sourceBitmapSize = from->GetPixelSize();
@@ -299,6 +350,101 @@ void writeDiagnosticPNGToPath(ID2D1RenderTarget* renderTarget, ID2D1Bitmap* bitm
     ASSERT(SUCCEEDED(hr));
 }
 
+static ID3D11DeviceContext1* immediateContext = nullptr;
+
+ID3D11DeviceContext1* dxgiImmediateContext()
+{
+    if (!immediateContext)
+        defaultDirectXDevice();
+
+    RELEASE_ASSERT(immediateContext);
+    return immediateContext;
+}
+
+ID3D11Device1* defaultDirectXDevice()
+{
+    static ID3D11Device1* defaultDevice1 = nullptr;
+
+    if (!defaultDevice1) {
+        int deviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+#ifndef NDEBUG
+        deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+        ID3D11Device* defaultDevice = nullptr;
+        D3D_FEATURE_LEVEL featureLevel = { };
+        ID3D11DeviceContext* immediateDeviceContext = nullptr;
+        HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, deviceFlags, nullptr, 0, D3D11_SDK_VERSION, &defaultDevice, &featureLevel, &immediateDeviceContext);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+
+        hr = defaultDevice->QueryInterface(&defaultDevice1);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+        defaultDevice1->AddRef();
+
+        hr = immediateDeviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&immediateContext));
+        RELEASE_ASSERT(SUCCEEDED(hr));
+        immediateContext->AddRef();
+    }
+
+    return defaultDevice1;
+}
+
+bool createDeviceAndContext(COMPtr<ID3D11Device1>& d3dDevice, COMPtr<ID3D11DeviceContext1>& immediateContext)
+{
+    int deviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+#ifndef NDEBUG
+    deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+    D3D_FEATURE_LEVEL featureLevel = { };
+    ID3D11Device* defaultDevice = nullptr;
+    ID3D11DeviceContext* immediateDeviceContext = nullptr;
+    HRESULT hr = ::D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, deviceFlags, nullptr, 0, D3D11_SDK_VERSION, &defaultDevice, &featureLevel, &immediateDeviceContext);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    hr = defaultDevice->QueryInterface(&d3dDevice);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+    defaultDevice->Release();
+
+    hr = immediateDeviceContext->QueryInterface(&immediateContext);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+    immediateContext->Release();
+    return true;
+}
+
+COMPtr<IDXGIDevice> toDXGIDevice(const COMPtr<ID3D11Device1>& d3dDevice)
+{
+    if (!d3dDevice)
+        return nullptr;
+
+    COMPtr<IDXGIDevice> dxgiDevice;
+    HRESULT hr = d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
+    if (!SUCCEEDED(hr))
+        return nullptr;
+
+    return dxgiDevice;
+}
+
+COMPtr<IDXGIFactory2> factoryForDXGIDevice(const COMPtr<IDXGIDevice>& device)
+{
+    if (!device)
+        return nullptr;
+
+    COMPtr<IDXGIAdapter> adaptor;
+    HRESULT hr = device->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&adaptor));
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    COMPtr<IDXGIFactory> factory;
+    hr = adaptor->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&factory));
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    COMPtr<IDXGIFactory2> factory2;
+    hr = factory->QueryInterface(&factory2); 
+    RELEASE_ASSERT(SUCCEEDED(hr));
+    
+    return factory2;
+}
+
 } // namespace Direct2D
 
 } // namespace WebCore
index c21f65e..3742dce 100644 (file)
 #include "COMPtr.h"
 #include "GraphicsTypes.h"
 #include "IntSize.h"
+#include "PlatformExportMacros.h"
 
 interface ID2D1Bitmap;
 interface ID2D1BitmapRenderTarget;
 interface ID2D1DCRenderTarget;
 interface ID2D1RenderTarget;
+interface ID3D11Device1;
+interface ID3D11DeviceContext1;
+interface IDXGIDevice;
+interface IDXGIFactory2;
+interface IDXGISurface1;
 interface IWICBitmapSource;
 interface IWICBitmap;
 
@@ -73,9 +79,17 @@ COMPtr<ID2D1RenderTarget> createRenderTargetFromWICBitmap(IWICBitmap*);
 COMPtr<ID2D1BitmapRenderTarget> createBitmapRenderTargetOfSize(const IntSize&, ID2D1RenderTarget* = nullptr, float deviceScaleFactor = 1.0);
 COMPtr<ID2D1BitmapRenderTarget> createBitmapRenderTarget(ID2D1RenderTarget* = nullptr);
 COMPtr<ID2D1DCRenderTarget> createGDIRenderTarget();
+COMPtr<IDXGISurface1> createDXGISurfaceOfSize(const IntSize&, ID3D11Device1*, bool crossProcess);
+COMPtr<ID2D1RenderTarget> createSurfaceRenderTarget(IDXGISurface1*);
 
 void copyRectFromOneSurfaceToAnother(ID2D1Bitmap* from, ID2D1Bitmap* to, const IntSize& sourceOffset, const IntRect&, const IntSize& destOffset = IntSize());
 
+WEBCORE_EXPORT ID3D11DeviceContext1* dxgiImmediateContext();
+WEBCORE_EXPORT ID3D11Device1* defaultDirectXDevice();
+WEBCORE_EXPORT bool createDeviceAndContext(COMPtr<ID3D11Device1>&, COMPtr<ID3D11DeviceContext1>&);
+WEBCORE_EXPORT COMPtr<IDXGIDevice> toDXGIDevice(const COMPtr<ID3D11Device1>&);
+WEBCORE_EXPORT COMPtr<IDXGIFactory2> factoryForDXGIDevice(const COMPtr<IDXGIDevice>&);
+
 void writeDiagnosticPNGToPath(ID2D1RenderTarget*, ID2D1Bitmap*, LPCWSTR fileName);
 
 } // namespace Direct2D
index 6e4fbeb..e3d69fe 100644 (file)
@@ -207,19 +207,19 @@ void GraphicsContext::restorePlatformState()
     Direct2D::restore(*platformContext());
 }
 
-void GraphicsContext::drawNativeImage(const COMPtr<ID2D1Bitmap>& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOperator, BlendMode blendMode, ImageOrientation orientation)
+void GraphicsContext::drawNativeImage(const COMPtr<ID2D1Bitmap>& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
 {
     if (paintingDisabled())
         return;
 
     if (m_impl) {
-        m_impl->drawNativeImage(image, imageSize, destRect, srcRect, compositeOperator, blendMode, orientation);
+        m_impl->drawNativeImage(image, imageSize, destRect, srcRect, options);
         return;
     }
 
     ASSERT(hasPlatformContext());
     auto& state = this->state();
-    Direct2D::drawNativeImage(*platformContext(), image.get(), imageSize, destRect, srcRect, compositeOperator, blendMode, orientation, state.imageInterpolationQuality, state.alpha, Direct2D::ShadowState(state));
+    Direct2D::drawNativeImage(*platformContext(), image.get(), imageSize, destRect, srcRect, options, state.alpha, Direct2D::ShadowState(state));
 }
 
 void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend)
@@ -423,19 +423,19 @@ void GraphicsContext::flush()
     Direct2D::flush(*platformContext());
 }
 
-void GraphicsContext::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator compositeOperator, BlendMode blendMode)
+void GraphicsContext::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, const ImagePaintingOptions& options)
 {
     if (paintingDisabled() || !patternTransform.isInvertible())
         return;
 
     if (m_impl) {
-        m_impl->drawPattern(image, destRect, tileRect, patternTransform, phase, spacing, compositeOperator, blendMode);
+        m_impl->drawPattern(image, destRect, tileRect, patternTransform, phase, spacing, options);
         return;
     }
 
     ASSERT(hasPlatformContext());
     if (auto tileImage = image.nativeImageForCurrentFrame(this))
-        Direct2D::drawPattern(*platformContext(), WTFMove(tileImage), IntSize(image.size()), destRect, tileRect, patternTransform, phase, compositeOperator, blendMode);
+        Direct2D::drawPattern(*platformContext(), WTFMove(tileImage), IntSize(image.size()), destRect, tileRect, patternTransform, phase, options.compositeOperator(), options.blendMode());
 }
 
 void GraphicsContext::clipToImageBuffer(ImageBuffer& buffer, const FloatRect& destRect)
index 1d1e7e6..00b1098 100644 (file)
@@ -283,17 +283,17 @@ ImageDrawResult GraphicsContextImplDirect2D::drawTiledImage(Image& image, const
     return GraphicsContextImpl::drawTiledImageImpl(graphicsContext(), image, destination, source, tileScaleFactor, hRule, vRule, imagePaintingOptions);
 }
 
-void GraphicsContextImplDirect2D::drawNativeImage(const NativeImagePtr& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOperator, BlendMode blendMode, ImageOrientation orientation)
+void GraphicsContextImplDirect2D::drawNativeImage(const NativeImagePtr& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
 {
     auto& state = graphicsContext().state();
-    Direct2D::drawNativeImage(m_platformContext, image.get(), imageSize, destRect, srcRect, compositeOperator, blendMode, orientation, state.imageInterpolationQuality, state.alpha, Direct2D::ShadowState(state));
+    Direct2D::drawNativeImage(m_platformContext, image.get(), imageSize, destRect, srcRect, options, state.alpha, Direct2D::ShadowState(state));
 }
 
-void GraphicsContextImplDirect2D::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize&, CompositeOperator compositeOperator, BlendMode blendMode)
+void GraphicsContextImplDirect2D::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize&, const ImagePaintingOptions& options)
 {
     auto* context = &graphicsContext();
     if (auto surface = image.nativeImageForCurrentFrame(context))
-        Direct2D::drawPattern(m_platformContext, WTFMove(surface), IntSize(image.size()), destRect, tileRect, patternTransform, phase, compositeOperator, blendMode);
+        Direct2D::drawPattern(m_platformContext, WTFMove(surface), IntSize(image.size()), destRect, tileRect, patternTransform, phase, options.compositeOperator(), options.blendMode());
 }
 
 void GraphicsContextImplDirect2D::drawRect(const FloatRect& rect, float borderThickness)
index f0bb96e..17f4417 100644 (file)
@@ -249,12 +249,12 @@ COMPtr<ID2D1Bitmap> ImageBuffer::copyNativeImage(BackingStoreCopy copyBehavior)
     return image;
 }
 
-void ImageBuffer::drawConsuming(std::unique_ptr<ImageBuffer> imageBuffer, GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode)
+void ImageBuffer::drawConsuming(std::unique_ptr<ImageBuffer> imageBuffer, GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
 {
-    imageBuffer->draw(destContext, destRect, srcRect, op, blendMode);
+    imageBuffer->draw(destContext, destRect, srcRect, options);
 }
 
-void ImageBuffer::draw(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode)
+void ImageBuffer::draw(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
 {
     FloatRect adjustedSrcRect = srcRect;
     adjustedSrcRect.scale(m_resolutionScale, m_resolutionScale);
@@ -265,10 +265,10 @@ void ImageBuffer::draw(GraphicsContext& destContext, const FloatRect& destRect,
     if (currentImageSize.isZero())
         return;
 
-    destContext.drawNativeImage(compatibleBitmap, currentImageSize, destRect, adjustedSrcRect, op, blendMode);
+    destContext.drawNativeImage(compatibleBitmap, currentImageSize, destRect, adjustedSrcRect, options);
 }
 
-void ImageBuffer::drawPattern(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
+void ImageBuffer::drawPattern(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, const ImagePaintingOptions& options)
 {
     FloatRect adjustedSrcRect = srcRect;
     adjustedSrcRect.scale(m_resolutionScale, m_resolutionScale);
@@ -276,14 +276,14 @@ void ImageBuffer::drawPattern(GraphicsContext& destContext, const FloatRect& des
     if (!context().isAcceleratedContext()) {
         if (&destContext == &context() || destContext.isAcceleratedContext()) {
             if (RefPtr<Image> copy = copyImage(CopyBackingStore)) // Drawing into our own buffer, need to deep copy.
-                copy->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, op, blendMode);
+                copy->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, options);
         } else {
             if (RefPtr<Image> imageForRendering = copyImage(DontCopyBackingStore))
-                imageForRendering->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, op, blendMode);
+                imageForRendering->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, options);
         }
     } else {
         if (RefPtr<Image> copy = copyImage(CopyBackingStore))
-            copy->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, op, blendMode);
+            copy->drawPattern(destContext, destRect, adjustedSrcRect, patternTransform, phase, spacing, options);
     }
 }
 
index 0af549f..c5be93f 100644 (file)
@@ -81,7 +81,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext& ctxt, const Float
         if (image && clampTo<int>(imageSize.height()) == static_cast<int>(srcSize.height()) && clampTo<int>(imageSize.width()) == static_cast<int>(srcSize.width())) {
             size_t currentFrame = m_currentFrame;
             m_currentFrame = i;
-            draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), compositeOp, BlendMode::Normal, DecodingMode::Synchronous, ImageOrientation::None);
+            draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), { compositeOp });
             m_currentFrame = currentFrame;
             return;
         }
@@ -89,7 +89,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext& ctxt, const Float
 
     // No image of the correct size was found, fallback to drawing the current frame
     FloatSize imageSize = BitmapImage::size();
-    draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), compositeOp, BlendMode::Normal, DecodingMode::Synchronous, ImageOrientation::None);
+    draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), { compositeOp });
 }
 
 } // namespace WebCore
index 5237ede..f6ddf1b 100644 (file)
@@ -247,7 +247,7 @@ NativeImagePtr SVGImage::nativeImage(const GraphicsContext* targetContext)
     PlatformContextDirect2D platformContext(nativeImageTarget.get());
     GraphicsContext localContext(&platformContext, GraphicsContext::BitmapRenderingContextType::GPUMemory);
 
-    draw(localContext, rect(), rect(), CompositeSourceOver, BlendMode::Normal, DecodingMode::Synchronous, ImageOrientation::None);
+    draw(localContext, rect(), rect(), { CompositeSourceOver, BlendMode::Normal, DecodingMode::Synchronous, ImageOrientation::None });
 
     COMPtr<ID2D1Bitmap> nativeImage;
     HRESULT hr = nativeImageTarget->GetBitmap(&nativeImage);
index 90194b9..04cb3f8 100644 (file)
@@ -1,3 +1,72 @@
+2019-08-30  Brent Fulgham  <bfulgham@apple.com>
+
+        [FTW] Use DirectX SharedResource as basis for SharedBitmap
+        https://bugs.webkit.org/show_bug.cgi?id=201157
+
+        Reviewed by Alex Christensen.
+
+        Currently an ID2D1Bitmap is used as the backing store for the SharedBitmap that is the
+        base type for sharing data between the WebContent Process and the UIProcess. However, this
+        involves moving GPU memory to local memory, copying that memory into the SharedMemory member
+        of the SharedBitmap, then building a new GPU bitmap on the UIProcess side from that SharedMemory.
+
+        Profiling indicates that this is the single largest place FTW WebKit spends its time.
+
+        Instead, we should use Direct2D's ability to render to an IDXGISurface, which can be shared
+        between multiple processes. This should avoid the GPU->CPU copy, the Direct2D-allocated
+        CPU->Shared Memory copy, and the shared memory to GPU copy.
+
+        Reviewed by Alex Christensen.
+
+        * Platform/SharedMemory.h:
+        * Platform/win/SharedMemoryWin.cpp:
+        (WebKit::SharedMemory::Handle::encodeHandle): Added.
+        (WebKit::SharedMemory::Handle::encode const): Use new helper function.
+        (WebKit::SharedMemory::Handle::decodeHandle): Added.
+        (WebKit::SharedMemory::Handle::decode): Use new helper function.
+        * PlatformFTW.cmake: Add D3X11 libraries.
+        * Shared/ShareableBitmap.cpp:
+        (WebKit::ShareableBitmap::Configuration::encode const): Encode shared resource handle for DX texture.
+        (WebKit::ShareableBitmap::Configuration::decode): Ditto (but decode).
+        (WebKit::ShareableBitmap::ShareableBitmap): Create SharedResource (if needed).
+        (WebKit::ShareableBitmap::~ShareableBitmap): Add cleanup code for SharedResoure.
+        (WebKit::ShareableBitmap::numBytesForSize): Only allocate a small memory store when using GPU textures.
+        * Shared/ShareableBitmap.h:
+        (WebKit::ShareableBitmap::dxSurface):
+        * Shared/win/ShareableBitmapDirect2D.cpp:
+        (WebKit::ShareableBitmap::createSharedResource): Added.
+        (WebKit::ShareableBitmap::disposeSharedResource): Added.
+        (WebKit::ShareableBitmap::leakSharedResource): Added.
+        (WebKit::ShareableBitmap::createGraphicsContext): Update for new data types.
+        (WebKit::ShareableBitmap::paint): Ditto.
+        (WebKit::ShareableBitmap::createDirect2DSurface): Update for new data types.
+        (WebKit::ShareableBitmap::createImage): Ditto.
+        (WebKit::createSurfaceFromData): Deleted.
+        (WebKit::ShareableBitmap::sync): Deleted.
+        * UIProcess/BackingStore.cpp:
+        * UIProcess/BackingStore.h:
+        * UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp:
+        * UIProcess/WebPageProxy.cpp:
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/win/BackingStoreDirect2D.cpp:
+        (WebKit::BackingStore::createBackend):
+        (WebKit::BackingStore::paint):
+        (WebKit::BackingStore::incorporateUpdate):
+        * UIProcess/win/PageClientImpl.cpp:
+        * UIProcess/win/WebPageProxyWin.cpp:
+        (WebKit::WebPageProxy::device const):
+        (WebKit::WebPageProxy::setDevice):
+        * UIProcess/win/WebView.cpp:
+        (WebKit::WebView::WebView): Initialize DirectX stuff.
+        (WebKit::WebView::paint): Use new DiretX drawing logic.
+        (WebKit::WebView::onSizeEvent): Update SwapChain's buffer sizes when resizing.
+        (WebKit::WebView::setupSwapChain): Added.
+        (WebKit::WebView::configureBackingStore): Added.
+        * UIProcess/win/WebView.h:
+        (WebKit::WebView::d3dDevice):
+        * WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:
+        (WebKit::DrawingAreaCoordinatedGraphics::display):
+
 2019-08-30  Chris Dumez  <cdumez@apple.com>
 
         [PSON] Bump the WebPage's identifier every time we process-swap
index 38e241f..a81b07e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2019 Apple Inc. All rights reserved.
  * Copyright (C) 2017 Sony Interactive Entertainment Inc.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -78,6 +78,10 @@ public:
         IPC::Attachment releaseAttachment() const;
         void adoptAttachment(IPC::Attachment&&);
 #endif
+#if OS(WINDOWS)
+        static void encodeHandle(IPC::Encoder&, HANDLE);
+        static Optional<HANDLE> decodeHandle(IPC::Decoder&);
+#endif
     private:
         friend class SharedMemory;
 #if USE(UNIX_DOMAIN_SOCKETS)
index 65a15ad..003b1b0 100644 (file)
@@ -66,11 +66,17 @@ void SharedMemory::Handle::encode(IPC::Encoder& encoder) const
 {
     encoder << static_cast<uint64_t>(m_size);
 
+    encodeHandle(encoder, m_handle);
+
     // Hand off ownership of our HANDLE to the receiving process. It will close it for us.
     // FIXME: If the receiving process crashes before it receives the memory, the memory will be
     // leaked. See <http://webkit.org/b/47502>.
-    encoder << reinterpret_cast<uint64_t>(m_handle);
     m_handle = 0;
+}
+
+void SharedMemory::Handle::encodeHandle(IPC::Encoder& encoder, HANDLE handle)
+{
+    encoder << reinterpret_cast<uint64_t>(handle);
 
     // Send along our PID so that the receiving process can duplicate the HANDLE for its own use.
     encoder << static_cast<uint32_t>(::GetCurrentProcessId());
@@ -113,21 +119,30 @@ bool SharedMemory::Handle::decode(IPC::Decoder& decoder, Handle& handle)
     if (!decoder.decode(size))
         return false;
 
+    auto processSpecificHandle = decodeHandle(decoder);
+    if (!processSpecificHandle)
+        return false;
+
+    handle.m_handle = processSpecificHandle.value();
+    handle.m_size = size;
+    return true;
+}
+
+Optional<HANDLE> SharedMemory::Handle::decodeHandle(IPC::Decoder& decoder)
+{
     uint64_t sourceHandle;
     if (!decoder.decode(sourceHandle))
-        return false;
+        return WTF::nullopt;
 
     uint32_t sourcePID;
     if (!decoder.decode(sourcePID))
-        return false;
+        return WTF::nullopt;
 
     HANDLE duplicatedHandle;
     if (!getDuplicatedHandle(reinterpret_cast<HANDLE>(sourceHandle), sourcePID, duplicatedHandle))
-        return false;
+        return WTF::nullopt;
 
-    handle.m_handle = duplicatedHandle;
-    handle.m_size = size;
-    return true;
+    return duplicatedHandle;
 }
 
 RefPtr<SharedMemory> SharedMemory::allocate(size_t size)
index 7af054d..84de970 100644 (file)
@@ -175,7 +175,9 @@ list(APPEND WebKit_LIBRARIES
     PRIVATE
         ${OPENSSL_LIBRARIES}
         D2d1.lib
+        D3d11.lib
         Dwrite
+        Dxgi.lib
         Dxguid
         WindowsCodecs
         mfuuid.lib
index 8fc5ad6..0814740 100644 (file)
@@ -68,6 +68,14 @@ void ShareableBitmap::Configuration::encode(IPC::Encoder& encoder) const
 #if PLATFORM(COCOA)
     encoder << colorSpace;
 #endif
+#if USE(DIRECT2D)
+    SharedMemory::Handle::encodeHandle(encoder, sharedResourceHandle);
+
+    // Hand off ownership of our HANDLE to the receiving process. It will close it for us.
+    // FIXME: If the receiving process crashes before it receives the memory, the memory will be
+    // leaked. See <http://webkit.org/b/47502>.
+    sharedResourceHandle = nullptr;
+#endif
 }
 
 bool ShareableBitmap::Configuration::decode(IPC::Decoder& decoder, Configuration& configuration)
@@ -78,6 +86,13 @@ bool ShareableBitmap::Configuration::decode(IPC::Decoder& decoder, Configuration
     if (!decoder.decode(configuration.colorSpace))
         return false;
 #endif
+#if USE(DIRECT2D)
+    auto processSpecificHandle = SharedMemory::Handle::decodeHandle(decoder);
+    if (!processSpecificHandle)
+        return false;
+
+    configuration.sharedResourceHandle = processSpecificHandle.value();
+#endif
     return true;
 }
 
@@ -156,12 +171,18 @@ ShareableBitmap::ShareableBitmap(const IntSize& size, Configuration configuratio
     , m_sharedMemory(sharedMemory)
     , m_data(nullptr)
 {
+#if USE(DIRECT2D)
+    createSharedResource();
+#endif
 }
 
 ShareableBitmap::~ShareableBitmap()
 {
     if (!isBackedBySharedMemory())
         fastFree(m_data);
+#if USE(DIRECT2D)
+    disposeSharedResource();
+#endif
 }
 
 void* ShareableBitmap::data() const
@@ -175,7 +196,12 @@ void* ShareableBitmap::data() const
 
 Checked<unsigned, RecordOverflow> ShareableBitmap::numBytesForSize(WebCore::IntSize size, const ShareableBitmap::Configuration& configuration)
 {
+#if USE(DIRECT2D)
+    // We pass references to GPU textures, so no need to allocate frame buffers here. Just send a small bit of data.
+    return sizeof(void*);
+#else
     return calculateBytesPerRow(size, configuration) * size.height();
+#endif
 }
 
 } // namespace WebKit
index fea9ca9..de7e75e 100644 (file)
@@ -42,6 +42,9 @@
 #if USE(DIRECT2D)
 interface ID2D1Bitmap;
 interface ID2D1RenderTarget;
+interface ID3D11Device1;
+interface IDXGIKeyedMutex;
+interface IDXGISurface1;
 
 #include <WebCore/COMPtr.h>
 #endif
@@ -60,6 +63,9 @@ public:
 #if PLATFORM(COCOA)
         ColorSpaceData colorSpace;
 #endif
+#if USE(DIRECT2D)
+        mutable HANDLE sharedResourceHandle { nullptr };
+#endif
 
         void encode(IPC::Encoder&) const;
         static bool decode(IPC::Decoder&, Configuration&);
@@ -132,8 +138,11 @@ public:
     // This is only safe to use when we know that the contents of the shareable bitmap won't change.
     RefPtr<cairo_surface_t> createCairoSurface();
 #elif USE(DIRECT2D)
-    COMPtr<ID2D1Bitmap> createDirect2DSurface(ID2D1RenderTarget*);
-    void sync(WebCore::GraphicsContext&);
+    COMPtr<ID2D1Bitmap> createDirect2DSurface(ID3D11Device1*, ID2D1RenderTarget*);
+    IDXGISurface1* dxSurface() { return m_surface.get(); }
+    void createSharedResource();
+    void disposeSharedResource();
+    void leakSharedResource();
 #endif
 
 private:
@@ -163,7 +172,8 @@ private:
     Configuration m_configuration;
 
 #if USE(DIRECT2D)
-    COMPtr<ID2D1Bitmap> m_bitmap;
+    COMPtr<IDXGISurface1> m_surface;
+    COMPtr<IDXGIKeyedMutex> m_surfaceMutex;
 #endif
 
     // If the shareable bitmap is backed by shared memory, this points to the shared memory object.
index 972215b..87b6a02 100644 (file)
@@ -28,6 +28,8 @@
 #include "config.h"
 #include "ShareableBitmap.h"
 
+#include "Decoder.h"
+#include "Encoder.h"
 #include <WebCore/BitmapImage.h>
 #include <WebCore/DIBPixelData.h>
 #include <WebCore/Direct2DOperations.h>
@@ -36,6 +38,8 @@
 #include <WebCore/NotImplemented.h>
 #include <WebCore/PlatformContextDirect2D.h>
 #include <d2d1_1.h>
+#include <d3d11_1.h>
+#include <dxgi1_2.h>
 #include <wincodec.h>
 #include <wtf/ProcessID.h>
 
@@ -59,21 +63,48 @@ unsigned ShareableBitmap::calculateBytesPerPixel(const Configuration&)
     return 4;
 }
 
-static inline COMPtr<IWICBitmap> createSurfaceFromData(void* data, const WebCore::IntSize& size)
+void ShareableBitmap::createSharedResource()
 {
-    const unsigned stride = strideForWidth(size.width());
-    return Direct2D::createDirect2DImageSurfaceWithData(data, size, stride);
+    // Don't create a shared resource if the configuration instructs us to use an existing one.
+    if (m_configuration.sharedResourceHandle)
+        return;
+
+    m_surface = Direct2D::createDXGISurfaceOfSize(m_size, nullptr, true);
+
+    COMPtr<IDXGIResource1> resourceData;
+    HRESULT hr = m_surface->QueryInterface(__uuidof(IDXGIResource), reinterpret_cast<void**>(&resourceData));
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    hr = resourceData->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr, &m_configuration.sharedResourceHandle);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+}
+
+void ShareableBitmap::disposeSharedResource()
+{
+    if (m_surfaceMutex)
+        m_surfaceMutex->ReleaseSync(1);
+    if (m_configuration.sharedResourceHandle)
+        ::CloseHandle(m_configuration.sharedResourceHandle);
+}
+
+void ShareableBitmap::leakSharedResource()
+{
+    m_configuration.sharedResourceHandle = nullptr;
 }
 
 std::unique_ptr<GraphicsContext> ShareableBitmap::createGraphicsContext()
 {
-    auto bitmapContext = Direct2D::createBitmapRenderTargetOfSize(m_size);
-    if (!bitmapContext)
+    // Lock the surface to the current device while rendering.
+    HRESULT hr = m_surface->QueryInterface(&m_surfaceMutex);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+    hr = m_surfaceMutex->AcquireSync(0, INFINITE);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    auto surfaceContext = Direct2D::createSurfaceRenderTarget(m_surface.get());
+    if (!surfaceContext)
         return nullptr;
 
-    HRESULT hr = bitmapContext->GetBitmap(&m_bitmap);
-    RELEASE_ASSERT(SUCCEEDED(hr));
-    return makeUnique<GraphicsContext>(GraphicsContextImplDirect2D::createFactory(bitmapContext.get()));
+    return makeUnique<GraphicsContext>(GraphicsContextImplDirect2D::createFactory(surfaceContext.get()));
 }
 
 void ShareableBitmap::paint(GraphicsContext& context, const IntPoint& dstPoint, const IntRect& srcRect)
@@ -83,7 +114,7 @@ void ShareableBitmap::paint(GraphicsContext& context, const IntPoint& dstPoint,
 
 void ShareableBitmap::paint(GraphicsContext& context, float scaleFactor, const IntPoint& dstPoint, const IntRect& srcRect)
 {
-    auto surface = createDirect2DSurface(context.platformContext()->renderTarget());
+    auto surface = createDirect2DSurface(nullptr, context.platformContext()->renderTarget());
 
 #ifndef _NDEBUG
     auto bitmapSize = surface->GetPixelSize();
@@ -99,16 +130,32 @@ void ShareableBitmap::paint(GraphicsContext& context, float scaleFactor, const I
     auto& state = context.state();
     auto& platformContext = *context.platformContext();
 
-    Direct2D::drawNativeImage(platformContext, surface.get(), m_size, destRect, srcRectScaled, state.compositeOperator, state.blendMode, ImageOrientation(), state.imageInterpolationQuality, state.alpha, Direct2D::ShadowState(state));
+    ImagePaintingOptions options { state.compositeOperator, state.blendMode, ImageOrientation(), state.imageInterpolationQuality };
+    Direct2D::drawNativeImage(platformContext, surface.get(), m_size, destRect, srcRectScaled, options, state.alpha, Direct2D::ShadowState(state));
 }
 
-COMPtr<ID2D1Bitmap> ShareableBitmap::createDirect2DSurface(ID2D1RenderTarget* renderTarget)
+COMPtr<ID2D1Bitmap> ShareableBitmap::createDirect2DSurface(ID3D11Device1* directXDevice, ID2D1RenderTarget* renderTarget)
 {
-    auto bitmapProperties = Direct2D::bitmapProperties();
+    if (!directXDevice)
+        directXDevice = Direct2D::defaultDirectXDevice();
+
+    COMPtr<ID3D11Texture2D> texture;
+    HRESULT hr = directXDevice->OpenSharedResource1(m_configuration.sharedResourceHandle, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
+    if (!SUCCEEDED(hr))
+        return nullptr;
+
+    hr = texture->QueryInterface(&m_surface);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    // Lock the surface to the current device while rendering.
+    hr = m_surface->QueryInterface(&m_surfaceMutex);
+    RELEASE_ASSERT(SUCCEEDED(hr));
+    hr = m_surfaceMutex->AcquireSync(1, INFINITE);
+    RELEASE_ASSERT(SUCCEEDED(hr));
 
     COMPtr<ID2D1Bitmap> bitmap;
-    uint32_t stride = 4 * m_size.width();
-    HRESULT hr = renderTarget->CreateBitmap(m_size, data(), stride, &bitmapProperties, &bitmap);
+    auto bitmapProperties = Direct2D::bitmapProperties();
+    hr = renderTarget->CreateSharedBitmap(__uuidof(IDXGISurface1), reinterpret_cast<void*>(m_surface.get()), &bitmapProperties, &bitmap);
     if (!SUCCEEDED(hr))
         return nullptr;
 
@@ -117,63 +164,11 @@ COMPtr<ID2D1Bitmap> ShareableBitmap::createDirect2DSurface(ID2D1RenderTarget* re
 
 RefPtr<Image> ShareableBitmap::createImage()
 {
-    auto surface = createDirect2DSurface(GraphicsContext::defaultRenderTarget());
+    auto surface = createDirect2DSurface(nullptr, GraphicsContext::defaultRenderTarget());
     if (!surface)
         return nullptr;
 
     return BitmapImage::create(WTFMove(surface));
 }
 
-void ShareableBitmap::sync(GraphicsContext& graphicsContext)
-{
-    ASSERT(m_bitmap);
-
-    graphicsContext.endDraw();
-
-    COMPtr<ID2D1DeviceContext> d2dDeviceContext;
-    HRESULT hr = graphicsContext.platformContext()->renderTarget()->QueryInterface(__uuidof(ID2D1DeviceContext), reinterpret_cast<void**>(&d2dDeviceContext));
-    ASSERT(SUCCEEDED(hr));
-
-    const unsigned stride = strideForWidth(m_size.width());
-
-    COMPtr<ID2D1Bitmap1> cpuBitmap;
-    D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_CPU_READ | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, Direct2D::pixelFormat());
-    hr = d2dDeviceContext->CreateBitmap(m_size, nullptr, stride, bitmapProperties, &cpuBitmap);
-    if (!SUCCEEDED(hr))
-        return;
-
-    hr = cpuBitmap->CopyFromBitmap(nullptr, m_bitmap.get(), nullptr);
-    if (!SUCCEEDED(hr))
-        return;
-
-    D2D1_MAPPED_RECT mappedData;
-    hr = cpuBitmap->Map(D2D1_MAP_OPTIONS_READ, &mappedData);
-    if (!SUCCEEDED(hr))
-        return;
-
-    if (mappedData.pitch == stride)
-        memcpy(data(), reinterpret_cast<char*>(mappedData.bits), stride * m_size.height());
-    else {
-        // Stride is different, so must do a rowwise copy:
-        Checked<int> height = m_size.height();
-        Checked<int> width = m_size.width();
-
-        const uint8_t* srcRows = mappedData.bits;
-        uint8_t* row = reinterpret_cast<uint8_t*>(data());
-
-        for (int y = 0; y < height.unsafeGet(); ++y) {
-            for (int x = 0; x < width.unsafeGet(); x++) {
-                int basex = x * 4;
-                reinterpret_cast<uint32_t*>(row + basex)[0] = reinterpret_cast<const uint32_t*>(srcRows + basex)[0];
-            }
-
-            srcRows += mappedData.pitch;
-            row += stride;
-        }
-    }
-
-    hr = cpuBitmap->Unmap();
-    ASSERT(SUCCEEDED(hr));
-}
-
 } // namespace WebKit
index 8945929..8627611 100644 (file)
@@ -31,6 +31,7 @@
 
 #if USE(DIRECT2D)
 #include <d2d1.h>
+#include <d3d11_1.h>
 #endif
 
 namespace WebKit {
index 76a72cf..fe3c63e 100644 (file)
@@ -36,6 +36,9 @@
 
 #if USE(DIRECT2D)
 interface ID2D1RenderTarget;
+interface ID3D11Device1;
+interface ID3D11DeviceContext1;
+interface ID3D11Texture2D;
 #endif
 
 namespace WebKit {
@@ -58,11 +61,11 @@ public:
 #if USE(CAIRO)
     typedef cairo_t* PlatformGraphicsContext;
 #elif USE(DIRECT2D)
-    struct GdiConnections {
-        HWND hwnd;
-        HDC hdc;
+    struct DXConnections {
+        ID3D11DeviceContext1* immediateContext { nullptr };
+        ID3D11Texture2D* backBuffer { nullptr };
     };
-    typedef GdiConnections PlatformGraphicsContext;
+    typedef DXConnections PlatformGraphicsContext;
 #endif
 
     void paint(PlatformGraphicsContext, const WebCore::IntRect&);
index 944db9c..d9e11a7 100644 (file)
 #include "SOAuthorizationCoordinator.h"
 #endif
 
+#if USE(DIRECT2D)
+#include <d3d11_1.h>
+#endif
+
 // This controls what strategy we use for mouse wheel coalescing.
 #define MERGE_WHEEL_EVENTS 1
 
index 4595064..7d5b59c 100644 (file)
@@ -152,6 +152,10 @@ class MediaSessionMetadata;
 }
 #endif
 
+#if USE(DIRECT2D)
+interface ID3D11Device1;
+#endif
+
 namespace API {
 class Attachment;
 class ContextMenuClient;
@@ -817,6 +821,10 @@ public:
 
 #if PLATFORM(WIN)
     PlatformViewWidget viewWidget();
+#if USE(DIRECT2D)
+    ID3D11Device1* device() const;
+    void setDevice(ID3D11Device1*);
+#endif
 #endif
 #if PLATFORM(WPE)
     struct wpe_view_backend* viewBackend();
@@ -2555,6 +2563,9 @@ private:
     };
     Optional<SpeechSynthesisData> m_speechSynthesisData;
 #endif
+#if USE(DIRECT2D)
+    COMPtr<ID3D11Device1> m_device;
+#endif
     bool m_isQuotaIncreaseDenied { false };
 };
 
index 7e5ec91..abdaa6e 100644 (file)
 #include <WebCore/GraphicsContextImplDirect2D.h>
 #include <WebCore/PlatformContextDirect2D.h>
 #include <d2d1.h>
+#include <d3d11_1.h>
+#include <dxgi.h>
 
 namespace WebKit {
 using namespace WebCore;
 
 std::unique_ptr<BackingStoreBackendDirect2D> BackingStore::createBackend()
 {
-    return makeUnique<BackingStoreBackendDirect2DImpl>(m_size, m_deviceScaleFactor);
+    return makeUnique<BackingStoreBackendDirect2DImpl>(m_size, m_deviceScaleFactor, m_webPageProxy.device());
 }
 
-void BackingStore::paint(GdiConnections gdiConnections, const IntRect& rect)
+void BackingStore::paint(DXConnections dxConnections, const IntRect& rect)
 {
     ASSERT(m_backend);
     ASSERT(m_backend->size() == m_size);
 
-    auto* renderTarget = m_backend->renderTarget();
+    COMPtr<ID3D11Resource> backBuffer;
+    HRESULT hr = dxConnections.backBuffer->QueryInterface(__uuidof(ID3D11Resource), reinterpret_cast<void**>(&backBuffer));
+    RELEASE_ASSERT(SUCCEEDED(hr));
 
-    RECT viewRect;
-    ::GetClientRect(gdiConnections.hwnd, &viewRect);
-    renderTarget->BindDC(gdiConnections.hdc, &viewRect);
+    COMPtr<ID3D11Resource> backingStore;
+    hr = m_backend->dxSurface()->QueryInterface(__uuidof(ID3D11Resource), reinterpret_cast<void**>(&backingStore));
+    RELEASE_ASSERT(SUCCEEDED(hr));
 
-    D2D1_RECT_F destRect = rect;
-
-    if (auto* patternBrush = m_backend->bitmapBrush()) {
-        renderTarget->BeginDraw();
-        renderTarget->FillRectangle(&destRect, patternBrush);
-        renderTarget->EndDraw();
-    }
+    CD3D11_BOX srcBox(rect.x(), rect.y(), 0, rect.x() + rect.width(), rect.y() + rect.height(), 1);
+    dxConnections.immediateContext->CopySubresourceRegion1(backBuffer.get(), 0, rect.x(), rect.y(), 0, backingStore.get(), 0, &srcBox, D3D11_COPY_DISCARD);
 }
 
 void BackingStore::incorporateUpdate(ShareableBitmap* bitmap, const UpdateInfo& updateInfo)
@@ -73,7 +72,9 @@ void BackingStore::incorporateUpdate(ShareableBitmap* bitmap, const UpdateInfo&
 
     IntPoint updateRectBoundsLocation = updateInfo.updateRectBounds.location();
 
-    COMPtr<ID2D1Bitmap> deviceUpdateBitmap = bitmap->createDirect2DSurface(m_backend->renderTarget());
+    COMPtr<ID2D1Bitmap> deviceUpdateBitmap = bitmap->createDirect2DSurface(m_webPageProxy.device(), m_backend->renderTarget());
+    if (!deviceUpdateBitmap)
+        return;
 
 #ifndef _NDEBUG
     auto deviceBitmapSize = deviceUpdateBitmap->GetPixelSize();
index 0307c4f..be61bbd 100644 (file)
@@ -34,6 +34,7 @@
 #include "WebView.h"
 #include <WebCore/DOMPasteAccess.h>
 #include <WebCore/NotImplemented.h>
+#include <d3d11_1.h>
 
 namespace WebKit {
 using namespace WebCore;
index 8d58592..bb047f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2019 Apple Inc. All rights reserved.
  * Copyright (C) 2018 Sony Interactive Entertainment Inc.
  *
  * Redistribution and use in source and binary forms, with or without
 #include <WebCore/SearchPopupMenuDB.h>
 #include <WebCore/UserAgent.h>
 
+#if USE(DIRECT2D)
+#include <d3d11_1.h>
+#endif
+
 namespace WebKit {
 
 void WebPageProxy::platformInitialize()
@@ -70,5 +74,17 @@ PlatformViewWidget WebPageProxy::viewWidget()
     return static_cast<PageClientImpl&>(pageClient()).viewWidget();
 }
 
+#if USE(DIRECT2D)
+ID3D11Device1* WebPageProxy::device() const
+{
+    return m_device.get();
+}
+
+void WebPageProxy::setDevice(ID3D11Device1* device)
+{
+    m_device = device;
+}
+#endif
+
 
 } // namespace WebKit
index 33aeab5..000350c 100644 (file)
@@ -69,6 +69,9 @@
 
 #if USE(DIRECT2D)
 #include <WebCore/Direct2DUtilities.h>
+#include <d3d11_1.h>
+#include <directxcolors.h> 
+#include <dxgi.h>
 #endif
 
 
@@ -245,8 +248,15 @@ WebView::WebView(RECT rect, const API::PageConfiguration& configuration, HWND pa
     m_page = processPool->createWebPage(*m_pageClient, WTFMove(pageConfiguration));
     m_page->initializeWebPage();
 
+    IntSize windowSize(rect.right - rect.left, rect.bottom - rect.top);
+#if USE(DIRECT2D)
+    Direct2D::createDeviceAndContext(m_d3dDevice, m_immediateContext);
+    m_page->setDevice(m_d3dDevice.get());
+    setupSwapChain(windowSize);
+#endif
+
     if (m_page->drawingArea())
-        m_page->drawingArea()->setSize(IntSize(rect.right - rect.left, rect.bottom - rect.top));
+        m_page->drawingArea()->setSize(windowSize);
 
 #if ENABLE(REMOTE_INSPECTOR)
     m_page->setURLSchemeHandlerForScheme(RemoteInspectorProtocolHandler::create(*m_page), "inspector");
@@ -491,8 +501,14 @@ void WebView::paint(HDC hdc, const IntRect& dirtyRect)
         cairo_destroy(context);
         cairo_surface_destroy(surface);
 #else
-        BackingStore::GdiConnections context { ::WindowFromDC(hdc), hdc };
-        drawingArea->paint(context, dirtyRect, unpaintedRegion);
+        COMPtr<ID3D11Texture2D> backBuffer; 
+        HRESULT hr = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)); 
+        if (SUCCEEDED(hr)) {
+            BackingStore::DXConnections context { m_immediateContext.get(), backBuffer.get() };
+            drawingArea->paint(context, dirtyRect, unpaintedRegion);
+        }
+
+        m_swapChain->Present(0, 0); 
 #endif
 
         auto unpaintedRects = unpaintedRegion.rects();
@@ -534,12 +550,29 @@ LRESULT WebView::onSizeEvent(HWND hwnd, UINT, WPARAM, LPARAM lParam, bool& handl
     int width = LOWORD(lParam);
     int height = HIWORD(lParam);
 
+    IntSize windowSize(width, height);
+
     if (m_page && m_page->drawingArea()) {
         // FIXME specify correctly layerPosition.
-        m_page->drawingArea()->setSize(IntSize(width, height), m_nextResizeScrollOffset);
+        m_page->drawingArea()->setSize(windowSize, m_nextResizeScrollOffset);
         m_nextResizeScrollOffset = IntSize();
     }
 
+#if USE(DIRECT2D)
+    if (m_swapChain) {
+        m_immediateContext->OMSetRenderTargets(0, nullptr, nullptr);
+
+        m_renderTargetView = nullptr;
+
+        // Preserve the existing buffer count (pass zero for count) and format (by passing DXGI_FORMAT_UNKNOWN).
+        // Automatically choose the width and height to match the client rect for the backing window (pass zeros for width/height).
+        HRESULT hr = m_swapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
+        RELEASE_ASSERT(SUCCEEDED(hr));
+
+        configureBackingStore(windowSize);
+    }
+#endif
+
     handled = true;
     return 0;
 }
@@ -917,4 +950,63 @@ void WebView::setToolTip(const String& toolTip)
     ::SendMessage(m_toolTipWindow, TTM_ACTIVATE, !toolTip.isEmpty(), 0);
 }
 
+#if USE(DIRECT2D)
+void WebView::setupSwapChain(const WebCore::IntSize& size)
+{
+    if (!m_d3dDevice)
+        return;
+
+    DXGI_SWAP_CHAIN_DESC1 swapChainDescription;
+    ::ZeroMemory(&swapChainDescription, sizeof(swapChainDescription));
+    swapChainDescription.Width = size.width();
+    swapChainDescription.Height = size.height();
+    swapChainDescription.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+    swapChainDescription.SampleDesc.Count = 1;
+    swapChainDescription.SampleDesc.Quality = 0;
+    swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+    swapChainDescription.BufferCount = 1;
+
+    auto factory = Direct2D::factoryForDXGIDevice(Direct2D::toDXGIDevice(m_d3dDevice));
+
+    IDXGISwapChain1* swapChain1 = nullptr;
+    HRESULT hr = factory->CreateSwapChainForHwnd(m_d3dDevice.get(), m_window, &swapChainDescription, nullptr, nullptr, &swapChain1);
+    if (SUCCEEDED(hr))
+        hr = swapChain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&m_swapChain));
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    factory->MakeWindowAssociation(m_window, 0);
+    configureBackingStore(size);
+}
+
+void WebView::configureBackingStore(const WebCore::IntSize& size)
+{
+    ASSERT(m_swapChain);
+    ASSERT(m_d3dDevice);
+    ASSERT(m_immediateContext);
+
+    // Create a render target view 
+    COMPtr<ID3D11Texture2D> backBuffer; 
+    HRESULT hr = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)); 
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    hr = m_d3dDevice->CreateRenderTargetView(backBuffer.get(), nullptr, &m_renderTargetView); 
+    RELEASE_ASSERT(SUCCEEDED(hr));
+
+    auto* renderTargetView = m_renderTargetView.get();
+    m_immediateContext->OMSetRenderTargets(1, &renderTargetView, nullptr);
+
+    // Setup the viewport 
+    D3D11_VIEWPORT viewport;
+    viewport.Width = (FLOAT)size.width();
+    viewport.Height = (FLOAT)size.height();
+    viewport.MinDepth = 0.0f;
+    viewport.MaxDepth = 1.0f;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    m_immediateContext->RSSetViewports(1, &viewport);
+
+    m_immediateContext->ClearRenderTargetView(m_renderTargetView.get(), DirectX::Colors::MidnightBlue); 
+}
+#endif
+
 } // namespace WebKit
index c210063..27f8972 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2019 Apple Inc. All rights reserved.
  * Copyright (C) 2017 Sony Interactive Entertainment Inc.
  *
  * Redistribution and use in source and binary forms, with or without
 #include <wtf/Forward.h>
 #include <wtf/RefPtr.h>
 
+#if USE(DIRECT2D)
+interface ID3D11Device1;
+interface ID3D11DeviceContext1;
+interface ID3D11RenderTargetView;
+interface IDXGISwapChain;
+#endif
+
+namespace WebCore {
+class IntSize;
+}
+
 namespace WebKit {
 
 class DrawingAreaProxy;
@@ -72,6 +83,10 @@ public:
 
     DrawingAreaProxy* drawingArea() { return page() ? page()->drawingArea() : nullptr; }
 
+#if USE(DIRECT2D)
+    ID3D11Device1* d3dDevice() { return m_d3dDevice.get(); }
+#endif
+
 private:
     WebView(RECT, const API::PageConfiguration&, HWND parentWindow);
 
@@ -128,6 +143,11 @@ private:
     // WebCore::WindowMessageListener
     virtual void windowReceivedMessage(HWND, UINT message, WPARAM, LPARAM);
 
+#if USE(DIRECT2D)
+    void setupSwapChain(const WebCore::IntSize&);
+    void configureBackingStore(const WebCore::IntSize&);
+#endif
+
     HWND m_window { nullptr };
     HWND m_topLevelParentWindow { nullptr };
     HWND m_toolTipWindow { nullptr };
@@ -147,6 +167,12 @@ private:
 
     std::unique_ptr<WebKit::PageClientImpl> m_pageClient;
     RefPtr<WebPageProxy> m_page;
+#if USE(DIRECT2D)
+    COMPtr<ID3D11Device1> m_d3dDevice;
+    COMPtr<ID3D11DeviceContext1> m_immediateContext;
+    COMPtr<ID3D11RenderTargetView> m_renderTargetView; 
+    COMPtr<IDXGISwapChain> m_swapChain;
+#endif
 };
 
 } // namespace WebKit
index a30025e..6ab1f9e 100644 (file)
@@ -45,6 +45,7 @@
 #include <WebCore/GraphicsContextImplDirect2D.h>
 #include <WebCore/PlatformContextDirect2D.h>
 #include <d2d1.h>
+#include <d3d11_1.h>
 #endif
 
 
@@ -760,8 +761,7 @@ void DrawingAreaCoordinatedGraphics::display(UpdateInfo& updateInfo)
     }
 
 #if USE(DIRECT2D)
-    if (graphicsContext)
-        bitmap->sync(*graphicsContext);
+    bitmap->leakSharedResource(); // It will be destroyed in the UIProcess.
 #endif
 
     // Layout can trigger more calls to setNeedsDisplay and we don't want to process them
index 3d032f8..ac7fda3 100644 (file)
@@ -1,3 +1,12 @@
+2019-08-30  Brent Fulgham  <bfulgham@apple.com>
+
+        [FTW] Use DirectX SharedResource as basis for SharedBitmap
+        https://bugs.webkit.org/show_bug.cgi?id=201157
+
+        Reviewed by Alex Christensen.
+
+        * PlatformFTW.cmake: Link to DirectX to avoid build failure.
+
 2019-08-19  Sihui Liu  <sihui_liu@apple.com>
 
         Remove IDB-specific quota
index ee67382..7cc5d41 100644 (file)
@@ -8,6 +8,8 @@ list(APPEND WebKitLegacy_SOURCES_Classes
 )
 list(APPEND WebKitLegacy_LIBRARIES
     ${OPENSSL_LIBRARIES}
+    PRIVATE D3D11.lib
+    PRIVATE Dxgi.lib
     PRIVATE mfuuid.lib
     PRIVATE strmiids.lib
     PRIVATE ${LIBXML2_LIBRARIES}