⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 249110 in webkit


Ignore:
Timestamp:
Aug 26, 2019, 12:08:57 PM (7 years ago)
Author:
Brent Fulgham
Message:

[FTW] Go back to ID2D1Bitmap as our NativeImage type
https://bugs.webkit.org/show_bug.cgi?id=201122

Reviewed by Alex Christensen.

In Bug 200093 I switched the OS type of NativeImagePtr from ID2D1Bitmap to IWICBitmap.
However, this was an ill-advised approach, because it dramatically harmed performance due
to the heavy use of software rendering.

I originally made this change because I thought this was the only way to get to the backing
bits of the bitmaps, but it turns out that a more recent Direct2D data type (ID2D1Bitmap1)
has the ability to map its memory to CPU-accessible memory, allowing software filter effects.

This patch switches back to the ID2D1Bitap data type, and hooks up the ID2D1Bitmap1 data type
to access the underlying memory of the bitmaps when software filter effects are used.

Source/WebCore:

  • platform/graphics/ImageBuffer.h:
  • platform/graphics/NativeImage.h:
  • platform/graphics/texmap/BitmapTextureGL.cpp:
  • platform/graphics/win/Direct2DOperations.cpp:
  • platform/graphics/win/Direct2DOperations.h:
  • platform/graphics/win/Direct2DUtilities.cpp:

(WebCore::Direct2D::writeDiagnosticPNGToPath):
(WebCore::Direct2D::writeImageToDiskAsPNG): Deleted.

  • platform/graphics/win/Direct2DUtilities.h:
  • platform/graphics/win/GraphicsContextDirect2D.cpp:
  • platform/graphics/win/ImageBufferDataDirect2D.cpp:
  • platform/graphics/win/ImageBufferDataDirect2D.h:
  • platform/graphics/win/ImageBufferDirect2D.cpp:
  • platform/graphics/win/ImageDecoderDirect2D.cpp:
  • platform/graphics/win/NativeImageDirect2D.cpp:
  • platform/graphics/win/PatternDirect2D.cpp:
  • svg/graphics/SVGImage.cpp:

Source/WebKit:

Reviewed by Alex Christensen.

  • Shared/ShareableBitmap.h:
  • Shared/win/ShareableBitmapDirect2D.cpp:
  • UIProcess/win/BackingStoreDirect2D.cpp:
  • WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:
Location:
trunk/Source
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r249109 r249110  
     12019-08-26  Brent Fulgham  <bfulgham@apple.com>
     2
     3        [FTW] Go back to ID2D1Bitmap as our NativeImage type
     4        https://bugs.webkit.org/show_bug.cgi?id=201122
     5
     6        Reviewed by Alex Christensen.
     7
     8        In Bug 200093 I switched the OS type of NativeImagePtr from ID2D1Bitmap to IWICBitmap.
     9        However, this was an ill-advised approach, because it dramatically harmed performance due
     10        to the heavy use of software rendering.
     11
     12        I originally made this change because I thought this was the only way to get to the backing
     13        bits of the bitmaps, but it turns out that a more recent Direct2D data type (ID2D1Bitmap1)
     14        has the ability to map its memory to CPU-accessible memory, allowing software filter effects.
     15
     16        This patch switches back to the ID2D1Bitap data type, and hooks up the ID2D1Bitmap1 data type
     17        to access the underlying memory of the bitmaps when software filter effects are used.
     18
     19        * platform/graphics/ImageBuffer.h:
     20        * platform/graphics/NativeImage.h:
     21        * platform/graphics/texmap/BitmapTextureGL.cpp:
     22        * platform/graphics/win/Direct2DOperations.cpp:
     23        * platform/graphics/win/Direct2DOperations.h:
     24        * platform/graphics/win/Direct2DUtilities.cpp:
     25        (WebCore::Direct2D::writeDiagnosticPNGToPath):
     26        (WebCore::Direct2D::writeImageToDiskAsPNG): Deleted.
     27        * platform/graphics/win/Direct2DUtilities.h:
     28        * platform/graphics/win/GraphicsContextDirect2D.cpp:
     29        * platform/graphics/win/ImageBufferDataDirect2D.cpp:
     30        * platform/graphics/win/ImageBufferDataDirect2D.h:
     31        * platform/graphics/win/ImageBufferDirect2D.cpp:
     32        * platform/graphics/win/ImageDecoderDirect2D.cpp:
     33        * platform/graphics/win/NativeImageDirect2D.cpp:
     34        * platform/graphics/win/PatternDirect2D.cpp:
     35        * svg/graphics/SVGImage.cpp:
     36
    1372019-08-26  Sam Weinig  <weinig@apple.com>
    238
  • trunk/Source/WebCore/platform/graphics/Image.cpp

    r248846 r249110  
    141141    const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
    142142{
    143     if (!nativeImageForCurrentFrame())
     143    if (!nativeImageForCurrentFrame(&ctxt))
    144144        return;
    145145
  • trunk/Source/WebCore/platform/graphics/ImageBuffer.h

    r249025 r249110  
    147147    void flushContext() const;
    148148#elif USE(DIRECT2D)
    149     COMPtr<IWICBitmap> copyNativeImage(BackingStoreCopy = CopyBackingStore) const;
    150     static COMPtr<IWICBitmap> sinkIntoNativeImage(std::unique_ptr<ImageBuffer>);
     149    COMPtr<ID2D1Bitmap> copyNativeImage(BackingStoreCopy = CopyBackingStore) const;
     150    static COMPtr<ID2D1Bitmap> sinkIntoNativeImage(std::unique_ptr<ImageBuffer>);
    151151    void flushContext() const;
    152152#endif
  • trunk/Source/WebCore/platform/graphics/NativeImage.h

    r248657 r249110  
    5656typedef RetainPtr<CGImageRef> NativeImagePtr;
    5757#elif USE(DIRECT2D)
    58 typedef COMPtr<IWICBitmap> NativeImagePtr;
     58typedef COMPtr<ID2D1Bitmap> NativeImagePtr;
    5959#elif USE(CAIRO)
    6060typedef RefPtr<cairo_surface_t> NativeImagePtr;
  • trunk/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp

    r247841 r249110  
    164164    bytesPerLine = cairo_image_surface_get_stride(surface);
    165165#elif USE(DIRECT2D)
    166     // We can't access the bitmap's memory when it is in the middle of a BeginDraw/EndDraw
    167     WICRect rcLock = { 0, 0, targetRect.width(), targetRect.height() };
    168 
    169     COMPtr<IWICBitmapLock> bitmapData;
    170     HRESULT hr = frameImage->Lock(&rcLock, WICBitmapLockRead, &bitmapData);
    171     if (!SUCCEEDED(hr))
    172         return;
    173 
    174     UINT stride = 0;
    175     hr = bitmapData->GetStride(&stride);
    176     if (!SUCCEEDED(hr))
    177         return;
    178 
    179     bytesPerLine = stride;
    180 
    181     UINT bufferSize = 0;
    182     WICInProcPointer dataPtr = nullptr;
    183     hr = bitmapData->GetDataPointer(&bufferSize, &dataPtr);
    184     if (!SUCCEEDED(hr))
    185         return;
    186 
    187     imageData = reinterpret_cast<char*>(dataPtr);
     166    notImplemented();
    188167#endif
    189168
  • trunk/Source/WebCore/platform/graphics/win/Direct2DOperations.cpp

    r248907 r249110  
    529529        drawWithoutShadow(platformContext, contextRect, drawFunction);
    530530    }
    531 
    532     flush(platformContext);
    533531}
    534532
     
    555553        drawWithoutShadow(platformContext, contextRect, drawFunction);
    556554    }
    557 
    558     flush(platformContext);
    559555}
    560556
     
    589585    else
    590586        drawWithoutShadow(platformContext, boundingRect, drawFunction);
    591 
    592     flush(platformContext);
    593587}
    594588
     
    641635    compositor->SetInput(1, bitmap);
    642636
    643     // Flip the context
    644     D2D1_MATRIX_3X2_F ctm;
    645     deviceContext->GetTransform(&ctm);
    646     auto translate = D2D1::Matrix3x2F::Translation(0.0f, deviceContext->GetSize().height);
    647     auto flip = D2D1::Matrix3x2F::Scale(D2D1::SizeF(1.0f, -1.0f));
    648     deviceContext->SetTransform(ctm * flip * translate);
    649 
    650637    deviceContext->DrawImage(compositor.get(), D2D1_INTERPOLATION_MODE_LINEAR);
    651638}
     
    656643
    657644    // Render the current geometry to a bitmap context
    658     COMPtr<ID2D1BitmapRenderTarget> bitmapTarget;
    659     HRESULT hr = context->CreateCompatibleRenderTarget(&bitmapTarget);
    660     RELEASE_ASSERT(SUCCEEDED(hr));
     645    COMPtr<ID2D1BitmapRenderTarget> bitmapTarget = createBitmapRenderTarget(context);
    661646
    662647    bitmapTarget->BeginDraw();
    663648    drawCommands(bitmapTarget.get());
    664     hr = bitmapTarget->EndDraw();
     649    HRESULT hr = bitmapTarget->EndDraw();
    665650    RELEASE_ASSERT(SUCCEEDED(hr));
    666651
     
    837822        drawWithoutShadow(platformContext, adjustedDestRect, drawFunction);
    838823
    839     flush(platformContext);
    840 
    841824    if (!stateSaver.didSave())
    842825        context->SetTransform(ctm);
    843826}
    844827
    845 void drawPattern(PlatformContextDirect2D& platformContext, IWICBitmap* tileImage, const IntSize& size, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator compositeOperator, BlendMode blendMode)
     828void drawPattern(PlatformContextDirect2D& platformContext, COMPtr<ID2D1Bitmap>&& tileImage, const IntSize& size, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator compositeOperator, BlendMode blendMode)
    846829{
    847830    auto context = platformContext.renderTarget();
     
    867850    // this does not allocate new bitmap memory.
    868851    if (size.width() > destRect.width() || size.height() > destRect.height()) {
    869         ASSERT(0);
    870         /*
    871852        float dpiX = 0;
    872853        float dpiY = 0;
     
    881862                tileImage = subImage;
    882863        }
    883         */
    884     }
    885 
    886     COMPtr<ID2D1Bitmap> bitmap;
    887     HRESULT hr = context->CreateBitmapFromWicBitmap(tileImage, nullptr, &bitmap);
    888     if (!SUCCEEDED(hr))
    889         return;
     864    }
    890865
    891866    COMPtr<ID2D1BitmapBrush> patternBrush;
    892     hr = context->CreateBitmapBrush(bitmap.get(), &bitmapBrushProperties, &brushProperties, &patternBrush);
     867    HRESULT hr = context->CreateBitmapBrush(tileImage.get(), &bitmapBrushProperties, &brushProperties, &patternBrush);
    893868    ASSERT(SUCCEEDED(hr));
    894869    if (!SUCCEEDED(hr))
     
    11101085    transparencyLayer.opacity = opacity;
    11111086
    1112     HRESULT hr = platformContext.renderTarget()->CreateCompatibleRenderTarget(&transparencyLayer.renderTarget);
    1113     RELEASE_ASSERT(SUCCEEDED(hr));
     1087    transparencyLayer.renderTarget = createBitmapRenderTarget(platformContext.renderTarget());
     1088
    11141089    platformContext.m_transparencyLayerStack.append(WTFMove(transparencyLayer));
    11151090
     
    12231198}
    12241199
     1200
     1201void copyBits(const uint8_t* srcRows, unsigned rowCount, unsigned colCount, unsigned srcStride, unsigned destStride, uint8_t* destRows)
     1202{
     1203    for (unsigned y = 0; y < rowCount; ++y) {
     1204        // Source data may be power-of-two sized, so we need to only copy the bits that
     1205        // correspond to the rectangle supplied by the caller.
     1206        const uint32_t* srcRow = reinterpret_cast<const uint32_t*>(srcRows + srcStride * y);
     1207        uint32_t* destRow = reinterpret_cast<uint32_t*>(destRows + destStride * y);
     1208        memcpy(destRow, srcRow, colCount);
     1209    }
     1210}
     1211
    12251212} // namespace Direct2D
     1213
    12261214} // namespace WebCore
    12271215
  • trunk/Source/WebCore/platform/graphics/win/Direct2DOperations.h

    r248444 r249110  
    3838#include "GraphicsContext.h"
    3939#include "GraphicsTypes.h"
     40#include <JavaScriptCore/Uint8ClampedArray.h>
    4041#include <d2d1.h>
    4142
     
    131132void drawNativeImage(PlatformContextDirect2D&, ID2D1Bitmap*, const FloatSize& imageSize, const FloatRect&, const FloatRect&, CompositeOperator, BlendMode, ImageOrientation, InterpolationQuality, float, const ShadowState&);
    132133void drawPath(PlatformContextDirect2D&, const Path&, const StrokeSource&, const ShadowState&);
    133 void drawPattern(PlatformContextDirect2D&, IWICBitmap*, const IntSize&, const FloatRect&, const FloatRect&, const AffineTransform&, const FloatPoint&, CompositeOperator, BlendMode);
     134void drawPattern(PlatformContextDirect2D&, COMPtr<ID2D1Bitmap>&&, const IntSize&, const FloatRect&, const FloatRect&, const AffineTransform&, const FloatPoint&, CompositeOperator, BlendMode);
    134135
    135136void drawWithoutShadow(PlatformContextDirect2D&, const FloatRect& boundingRect, const WTF::Function<void(ID2D1RenderTarget*)>& drawCommands);
  • trunk/Source/WebCore/platform/graphics/win/Direct2DUtilities.cpp

    r248907 r249110  
    116116
    117117    COMPtr<IWICBitmap> surface;
    118     HRESULT hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmapFromMemory(size.width(), size.height(), GUID_WICPixelFormat32bppPBGRA, stride, static_cast<UINT>(numBytes.unsafeGet()), reinterpret_cast<BYTE*>(data), &surface);
     118    HRESULT hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmapFromMemory(size.width(), size.height(), wicBitmapFormat(), stride, static_cast<UINT>(numBytes.unsafeGet()), reinterpret_cast<BYTE*>(data), &surface);
    119119    if (!SUCCEEDED(hr))
    120120        return nullptr;
     
    126126{
    127127    COMPtr<IWICBitmap> surface;
    128     HRESULT hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmap(size.width(), size.height(), GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &surface);
     128    HRESULT hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmap(size.width(), size.height(), wicBitmapFormat(), WICBitmapCacheOnDemand, &surface);
    129129    if (!SUCCEEDED(hr))
    130130        return nullptr;
     
    133133}
    134134
     135D2D1_PIXEL_FORMAT pixelFormatForSoftwareManipulation()
     136{
     137    return D2D1::PixelFormat(DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
     138}
     139
     140D2D1_PIXEL_FORMAT pixelFormat()
     141{
     142    // 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
     143    return D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
     144}
     145
     146GUID wicBitmapFormat()
     147{
     148    // This is the WIC format compatible with DXGI_FORMAT_B8G8R8A8_UNORM. It is also supposedly the most efficient in-memory
     149    // representation for WIC images.
     150    return GUID_WICPixelFormat32bppPBGRA;
     151}
     152
     153D2D1_BITMAP_PROPERTIES bitmapProperties()
     154{
     155    return D2D1::BitmapProperties(pixelFormat());
     156}
     157
    135158COMPtr<ID2D1Bitmap> createBitmap(ID2D1RenderTarget* renderTarget, const IntSize& size)
    136159{
    137     auto bitmapProperties = D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED));
     160    auto bitmapCreateProperties = bitmapProperties();
    138161
    139162    COMPtr<ID2D1Bitmap> bitmap;
    140163    D2D1_SIZE_U bitmapSize = size;
    141     HRESULT hr = renderTarget->CreateBitmap(bitmapSize, bitmapProperties, &bitmap);
     164    HRESULT hr = renderTarget->CreateBitmap(bitmapSize, bitmapCreateProperties, &bitmap);
    142165    if (!SUCCEEDED(hr))
    143166        return nullptr;
     
    146169}
    147170
     171D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties()
     172{
     173    return D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
     174        pixelFormat(), 0, 0, D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE, D2D1_FEATURE_LEVEL_DEFAULT);
     175}
     176
    148177COMPtr<ID2D1RenderTarget> createRenderTargetFromWICBitmap(IWICBitmap* bitmapSource)
    149178{
    150     auto targetProperties = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
    151         D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
    152         0, 0, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT);
     179    auto targetProperties = renderTargetProperties();
    153180
    154181    COMPtr<ID2D1RenderTarget> bitmapContext;
     
    162189COMPtr<ID2D1DCRenderTarget> createGDIRenderTarget()
    163190{
    164     auto targetProperties = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
    165         D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
    166         0, 0, D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE, D2D1_FEATURE_LEVEL_DEFAULT);
     191    auto targetProperties = renderTargetProperties();
    167192
    168193    COMPtr<ID2D1DCRenderTarget> renderTarget;
     
    174199}
    175200
     201COMPtr<ID2D1BitmapRenderTarget> createBitmapRenderTarget(ID2D1RenderTarget* renderTarget)
     202{
     203    if (!renderTarget)
     204        renderTarget = GraphicsContext::defaultRenderTarget();
     205
     206    COMPtr<ID2D1BitmapRenderTarget> bitmapContext;
     207    HRESULT hr = renderTarget->CreateCompatibleRenderTarget(nullptr, nullptr, nullptr, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, &bitmapContext);
     208    if (!SUCCEEDED(hr))
     209        return nullptr;
     210
     211    return bitmapContext;
     212}
     213
     214COMPtr<ID2D1BitmapRenderTarget> createBitmapRenderTargetOfSize(const IntSize& size, ID2D1RenderTarget* renderTarget, float deviceScaleFactor)
     215{
     216    UNUSED_PARAM(deviceScaleFactor);
     217
     218    if (!renderTarget)
     219        renderTarget = GraphicsContext::defaultRenderTarget();
     220
     221    COMPtr<ID2D1BitmapRenderTarget> bitmapContext;
     222    auto desiredSize = D2D1::SizeF(size.width(), size.height());
     223    D2D1_SIZE_U pixelSize = size;
     224    HRESULT hr = renderTarget->CreateCompatibleRenderTarget(&desiredSize, &pixelSize, nullptr, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, &bitmapContext);
     225    if (!SUCCEEDED(hr))
     226        return nullptr;
     227
     228    return bitmapContext;
     229}
     230
    176231void copyRectFromOneSurfaceToAnother(ID2D1Bitmap* from, ID2D1Bitmap* to, const IntSize& sourceOffset, const IntRect& rect, const IntSize& destOffset)
    177232{
     
    200255}
    201256
    202 void writeImageToDiskAsPNG(ID2D1RenderTarget* renderTarget, ID2D1Bitmap* bitmap, LPCWSTR fileName)
     257void writeDiagnosticPNGToPath(ID2D1RenderTarget* renderTarget, ID2D1Bitmap* bitmap, LPCWSTR fileName)
    203258{
    204259    COMPtr<IWICBitmapEncoder> wicBitmapEncoder;
  • trunk/Source/WebCore/platform/graphics/win/Direct2DUtilities.h

    r248907 r249110  
    3535
    3636interface ID2D1Bitmap;
     37interface ID2D1BitmapRenderTarget;
    3738interface ID2D1DCRenderTarget;
    3839interface ID2D1RenderTarget;
    3940interface IWICBitmapSource;
    4041interface IWICBitmap;
     42
     43struct D2D1_BITMAP_PROPERTIES;
     44struct D2D1_PIXEL_FORMAT;
     45struct D2D1_RENDER_TARGET_PROPERTIES;
    4146
    4247namespace WebCore {
     
    4954namespace Direct2D {
    5055
     56GUID wicBitmapFormat();
     57D2D1_PIXEL_FORMAT pixelFormat(); // BGRA
     58D2D1_PIXEL_FORMAT pixelFormatForSoftwareManipulation(); // RGBA
     59D2D1_BITMAP_PROPERTIES bitmapProperties();
     60D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties();
     61
     62void inPlaceSwizzle(uint8_t* byteData, unsigned length, bool applyPremultiplication = false);
     63
    5164IntSize bitmapSize(IWICBitmapSource*);
    5265FloatSize bitmapSize(ID2D1Bitmap*);
     
    5871COMPtr<IWICBitmap> createDirect2DImageSurfaceWithData(void* data, const IntSize&, unsigned stride);
    5972COMPtr<ID2D1RenderTarget> createRenderTargetFromWICBitmap(IWICBitmap*);
     73COMPtr<ID2D1BitmapRenderTarget> createBitmapRenderTargetOfSize(const IntSize&, ID2D1RenderTarget* = nullptr, float deviceScaleFactor = 1.0);
     74COMPtr<ID2D1BitmapRenderTarget> createBitmapRenderTarget(ID2D1RenderTarget* = nullptr);
    6075COMPtr<ID2D1DCRenderTarget> createGDIRenderTarget();
    6176
    6277void copyRectFromOneSurfaceToAnother(ID2D1Bitmap* from, ID2D1Bitmap* to, const IntSize& sourceOffset, const IntRect&, const IntSize& destOffset = IntSize());
    6378
    64 void writeImageToDiskAsPNG(ID2D1RenderTarget*, ID2D1Bitmap*, LPCWSTR fileName);
     79void writeDiagnosticPNGToPath(ID2D1RenderTarget*, ID2D1Bitmap*, LPCWSTR fileName);
    6580
    6681} // namespace Direct2D
  • trunk/Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp

    r248846 r249110  
    2929#include "COMPtr.h"
    3030#include "Direct2DOperations.h"
     31#include "Direct2DUtilities.h"
    3132#include "DisplayListRecorder.h"
    3233#include "FloatRoundedRect.h"
     
    5556{
    5657    // Create a DC render target.
    57     auto targetProperties = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
    58         D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
    59         0, 0, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT);
     58    auto targetProperties = Direct2D::renderTargetProperties();
    6059
    6160    HRESULT hr = GraphicsContext::systemFactory()->CreateDCRenderTarget(&targetProperties, renderTarget);
     
    10099        HRESULT hr = systemFactory()->CreateHwndRenderTarget(&renderTargetProperties, &hwndRenderTargetProperties, reinterpret_cast<ID2D1HwndRenderTarget**>(&defaultRenderTarget));
    101100        RELEASE_ASSERT(SUCCEEDED(hr));
     101        defaultRenderTarget->AddRef();
    102102    }
    103103
     
    114114    DIBPixelData pixelData(bitmap);
    115115
    116     auto targetProperties = D2D1::RenderTargetProperties();
    117     targetProperties.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
     116    auto targetProperties = Direct2D::renderTargetProperties();
    118117
    119118    COMPtr<ID2D1DCRenderTarget> renderTarget;
     
    209208}
    210209
    211 void GraphicsContext::drawNativeImage(const COMPtr<IWICBitmap>& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOperator, BlendMode blendMode, ImageOrientation orientation)
     210void GraphicsContext::drawNativeImage(const COMPtr<ID2D1Bitmap>& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOperator, BlendMode blendMode, ImageOrientation orientation)
    212211{
    213212    if (paintingDisabled())
     
    241240    ASSERT(pixelData.bitsPerPixel() == 32);
    242241
    243     auto bitmapProperties = D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED));
     242    auto bitmapProperties = Direct2D::bitmapProperties();
    244243
    245244    ASSERT(hasPlatformContext());
     
    436435
    437436    ASSERT(hasPlatformContext());
    438     if (auto tileImage = image.nativeImageForCurrentFrame())
    439         Direct2D::drawPattern(*platformContext(), tileImage.get(), IntSize(image.size()), destRect, tileRect, patternTransform, phase, compositeOperator, blendMode);
     437    if (auto tileImage = image.nativeImageForCurrentFrame(this))
     438        Direct2D::drawPattern(*platformContext(), WTFMove(tileImage), IntSize(image.size()), destRect, tileRect, patternTransform, phase, compositeOperator, blendMode);
    440439}
    441440
  • trunk/Source/WebCore/platform/graphics/win/GraphicsContextImplDirect2D.cpp

    r248846 r249110  
    292292void GraphicsContextImplDirect2D::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize&, CompositeOperator compositeOperator, BlendMode blendMode)
    293293{
    294     if (auto surface = image.nativeImageForCurrentFrame())
    295         Direct2D::drawPattern(m_platformContext, surface.get(), IntSize(image.size()), destRect, tileRect, patternTransform, phase, compositeOperator, blendMode);
     294    auto* context = &graphicsContext();
     295    if (auto surface = image.nativeImageForCurrentFrame(context))
     296        Direct2D::drawPattern(m_platformContext, WTFMove(surface), IntSize(image.size()), destRect, tileRect, patternTransform, phase, compositeOperator, blendMode);
    296297}
    297298
     
    422423        return;
    423424
    424 
    425     if (auto surface = image->nativeImageForCurrentFrame())
     425    auto* context = &graphicsContext();
     426    if (auto surface = image->nativeImageForCurrentFrame(context))
    426427        notImplemented();
    427428}
  • trunk/Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.cpp

    r247841 r249110  
    3030
    3131#include "BitmapInfo.h"
     32#include "Direct2DUtilities.h"
    3233#include "GraphicsContext.h"
    3334#include "HWndDC.h"
    3435#include "IntRect.h"
    3536#include "NotImplemented.h"
     37#include "PlatformContextDirect2D.h"
    3638#include <JavaScriptCore/JSCInlines.h>
    3739#include <JavaScriptCore/TypedArrayInlines.h>
     
    4345namespace WebCore {
    4446
    45 RefPtr<Uint8ClampedArray> ImageBufferData::getData(AlphaPremultiplication, const IntRect& rect, const IntSize& size, bool /* accelerateRendering */, float /* resolutionScale */) const
     47// Swizzle the red and blue bytes of the pixels in a buffer
     48template <AlphaPremultiplication desiredFormat>
     49void swizzleAndPremultiply(const uint8_t* srcRows, unsigned rowCount, unsigned colCount, unsigned srcStride, unsigned destStride, uint8_t* destRows)
     50{
     51    for (unsigned y = 0; y < rowCount; ++y) {
     52        // Source data may be power-of-two sized, so we need to only copy the bits that
     53        // correspond to the rectangle supplied by the caller.
     54        const uint32_t* srcRow = reinterpret_cast<const uint32_t*>(srcRows + srcStride * y);
     55        uint8_t* destRow = destRows + destStride * y;
     56        for (unsigned x = 0; x < colCount; ++x) {
     57            unsigned bytePosition = x * 4;
     58            const uint32_t* srcPixel = srcRow + x;
     59
     60            // Software filters expect (P)RGBA bytes. We need to swizzle from Direct2D's PBGRA to be compatible.
     61            uint32_t alpha = (*srcPixel & 0xFF000000) >> 24;
     62            uint32_t red = (*srcPixel & 0x00FF0000) >> 16;
     63            uint32_t green = (*srcPixel & 0x0000FF00) >> 8;
     64            uint32_t blue = (*srcPixel & 0x000000FF);
     65
     66            if (desiredFormat == AlphaPremultiplication::Unpremultiplied) {
     67                if (alpha && alpha != 255) {
     68                    red = red * 255 / alpha;
     69                    green = green * 255 / alpha;
     70                    blue = blue * 255 / alpha;
     71                }
     72            }
     73
     74            destRow[bytePosition]     = red;
     75            destRow[bytePosition + 1] = green;
     76            destRow[bytePosition + 2] = blue;
     77            destRow[bytePosition + 3] = alpha;
     78        }
     79    }
     80}
     81
     82RefPtr<Uint8ClampedArray> ImageBufferData::getData(AlphaPremultiplication desiredFormat, const IntRect& rect, const IntSize& size, bool /* accelerateRendering */, float /* resolutionScale */) const
    4683{
    4784    auto numBytes = rect.area<RecordOverflow>() * 4;
     
    5491        return nullptr;
    5592
    56     WICRect rcLock = { 0, 0, rect.width(), rect.height() };
    57 
    58     // We cannot access the data backing an IWICBitmap while an active draw session is open.
     93    if (!bitmap)
     94        return result;
     95
    5996    context->endDraw();
    6097
    61     COMPtr<IWICBitmapLock> bitmapDataLock;
    62     HRESULT hr = bitmapSource->Lock(&rcLock, WICBitmapLockRead, &bitmapDataLock);
    63     if (SUCCEEDED(hr)) {
    64         UINT bufferSize = 0;
    65         WICInProcPointer dataPtr = nullptr;
    66         hr = bitmapDataLock->GetDataPointer(&bufferSize, &dataPtr);
    67         if (SUCCEEDED(hr))
    68             memcpy(result->data(), reinterpret_cast<char*>(dataPtr), numBytes.unsafeGet());
     98    COMPtr<ID2D1DeviceContext> d2dDeviceContext;
     99    HRESULT hr = platformContext->renderTarget()->QueryInterface(__uuidof(ID2D1DeviceContext), reinterpret_cast<void**>(&d2dDeviceContext));
     100    ASSERT(SUCCEEDED(hr));
     101
     102    auto bytesPerRowInData = size.width() * 4;
     103
     104    COMPtr<ID2D1Bitmap1> cpuBitmap;
     105    D2D1_BITMAP_PROPERTIES1 bitmapProperties2 = D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_CPU_READ | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, Direct2D::pixelFormat());
     106    hr = d2dDeviceContext->CreateBitmap(size, nullptr, bytesPerRowInData, bitmapProperties2, &cpuBitmap);
     107    if (!SUCCEEDED(hr))
     108        return nullptr;
     109
     110    D2D1_POINT_2U targetPos = D2D1::Point2U();
     111    D2D1_RECT_U dataRect = rect;
     112    hr = cpuBitmap->CopyFromBitmap(&targetPos, bitmap.get(), &dataRect);
     113    if (!SUCCEEDED(hr))
     114        return nullptr;
     115
     116    D2D1_MAPPED_RECT mappedData;
     117    hr = cpuBitmap->Map(D2D1_MAP_OPTIONS_READ, &mappedData);
     118    if (!SUCCEEDED(hr))
     119        return nullptr;
     120
     121    // Software filters expect RGBA bytes. We need to swizzle from Direct2D's BGRA to be compatible.
     122    Checked<int> height = rect.height();
     123    Checked<int> width = rect.width();
     124
     125    if (desiredFormat == AlphaPremultiplication::Unpremultiplied)
     126        swizzleAndPremultiply<AlphaPremultiplication::Unpremultiplied>(mappedData.bits, height.unsafeGet(), width.unsafeGet(), mappedData.pitch, bytesPerRowInData, resultData);
     127    else
     128        swizzleAndPremultiply<AlphaPremultiplication::Premultiplied>(mappedData.bits, height.unsafeGet(), width.unsafeGet(), mappedData.pitch, bytesPerRowInData, resultData);
     129
     130    hr = cpuBitmap->Unmap();
     131    ASSERT(SUCCEEDED(hr));
     132
     133    context->beginDraw();
     134
     135    return result;
     136}
     137
     138// Swizzle the red and blue bytes of the pixels in a buffer
     139template <AlphaPremultiplication sourceFormat>
     140void inPlaceSwizzle(uint8_t* byteData, unsigned byteCount)
     141{
     142    size_t pixelCount = byteCount / 4;
     143    auto* pixelData = reinterpret_cast<uint32_t*>(byteData);
     144
     145    for (size_t i = 0; i < pixelCount; ++i) {
     146        uint32_t pixel = *pixelData;
     147        size_t bytePosition = i * 4;
     148
     149        uint32_t alpha = (pixel & 0xFF000000) >> 24;
     150        uint32_t red = (pixel & 0x00FF0000) >> 16;
     151        uint32_t green = (pixel & 0x0000FF00) >> 8;
     152        uint32_t blue = (pixel & 0x000000FF);
     153
     154        // (P)RGBA -> PBGRA
     155        if (sourceFormat == AlphaPremultiplication::Unpremultiplied) {
     156            if (alpha != 255) {
     157                red = (red * alpha + 254) / 255;
     158                green = (green * alpha + 254) / 255;
     159                blue = (blue * alpha + 254) / 255;
     160            }
     161        }
     162
     163        *pixelData = (alpha << 24) | red  << 16 | green  << 8 | blue;
     164        ++pixelData;
    69165    }
    70 
    71     // Once we are done modifying the data, unlock the bitmap
    72     bitmapDataLock = nullptr;
    73 
    74     context->beginDraw();
    75 
    76     return result;
    77166}
    78167
     
    115204        return;
    116205
     206    context->endDraw();
     207
     208    auto pixelSize = bitmap->GetPixelSize();
     209    ASSERT(pixelSize.width >= sourceSize.width());
     210    ASSERT(pixelSize.width >= size.width());
     211    ASSERT(pixelSize.height >= sourceSize.height());
     212    ASSERT(pixelSize.height >= size.height());
     213
     214    // Software generated bitmap data is in RGBA. We need to swizzle to premultiplied BGRA to be compatible
     215    // with the HWND/HDC render backing we use.
     216    if (sourceFormat == AlphaPremultiplication::Unpremultiplied)
     217        inPlaceSwizzle<AlphaPremultiplication::Unpremultiplied>(source.data(), source.length()); // RGBA -> PBGRA
     218    else
     219        inPlaceSwizzle<AlphaPremultiplication::Premultiplied>(source.data(), source.length()); // PRGBA -> PBGRA
     220
     221    COMPtr<ID2D1BitmapRenderTarget> bitmapRenderTarget;
     222    HRESULT hr = platformContext->renderTarget()->QueryInterface(__uuidof(ID2D1BitmapRenderTarget), reinterpret_cast<void**>(&bitmapRenderTarget));
     223    ASSERT(SUCCEEDED(hr));
     224
     225    auto bytesPerRowInData = sourceRect.width() * 4;
     226
     227    COMPtr<ID2D1Bitmap> swizzledBitmap;
     228    D2D1_BITMAP_PROPERTIES bitmapProperties = D2D1::BitmapProperties(Direct2D::pixelFormat());
     229    hr = bitmapRenderTarget->CreateBitmap(sourceSize, source.data(), bytesPerRowInData, bitmapProperties, &swizzledBitmap);
     230    if (!SUCCEEDED(hr))
     231        return;
     232
     233    D2D1_POINT_2U destPointD2D = destPoint;
     234    D2D1_RECT_U srcRect = sourceRect;
     235    hr = bitmap->CopyFromMemory(&srcRect, source.data(), bytesPerRowInData);
     236    ASSERT(SUCCEEDED(hr));
     237
     238    context->beginDraw();
     239}
     240
     241COMPtr<ID2D1Bitmap> ImageBufferData::compatibleBitmap(ID2D1RenderTarget* renderTarget)
     242{
     243    if (!renderTarget)
     244        return bitmap;
     245
     246    if (platformContext->renderTarget() == renderTarget)
     247        return bitmap;
     248
     249    auto size = bitmap->GetPixelSize();
     250
     251    Checked<unsigned, RecordOverflow> numBytes = size.width * size.height * 4;
     252    if (numBytes.hasOverflowed())
     253        return nullptr;
     254
     255    // Copy the bits from current renderTarget to the output target.
    117256    // We cannot access the data backing an IWICBitmap while an active draw session is open.
    118257    context->endDraw();
    119258
    120     WICRect rcLock = { 0, 0, sourceSize.width(), sourceSize.height() };
    121 
    122     COMPtr<IWICBitmapLock> bitmapDataLock;
    123     HRESULT hr = bitmapSource->Lock(&rcLock, WICBitmapLockWrite, &bitmapDataLock);
    124     if (!SUCCEEDED(hr))
    125         return;
    126 
    127     UINT stride = 0;
    128     hr = bitmapDataLock->GetStride(&stride);
    129     if (!SUCCEEDED(hr))
    130         return;
    131 
    132     UINT bufferSize = 0;
    133     WICInProcPointer dataPtr = nullptr;
    134     hr = bitmapDataLock->GetDataPointer(&bufferSize, &dataPtr);
    135     if (!SUCCEEDED(hr))
    136         return;
    137 
    138     ASSERT(bufferSize == source.byteLength());
    139 
    140     unsigned srcBytesPerRow = 4 * sourceSize.width();
    141 
    142     ASSERT(srcBytesPerRow == stride);
    143 
    144     const uint8_t* srcRows = source.data() + (originy * srcBytesPerRow + originx * 4).unsafeGet();
    145 
    146     auto row = makeUniqueArray<uint8_t>(srcBytesPerRow);
    147 
    148     for (int y = 0; y < height.unsafeGet(); ++y) {
    149         for (int x = 0; x < width.unsafeGet(); x++) {
    150             int basex = x * 4;
    151             uint8_t alpha = srcRows[basex + 3];
    152             if (sourceFormat == AlphaPremultiplication::Unpremultiplied && alpha != 255) {
    153                 row[basex] = (srcRows[basex] * alpha + 254) / 255;
    154                 row[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
    155                 row[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
    156                 row[basex + 3] = alpha;
    157             } else
    158                 reinterpret_cast<uint32_t*>(row.get() + basex)[0] = reinterpret_cast<const uint32_t*>(srcRows + basex)[0];
    159         }
    160 
    161         memcpy(reinterpret_cast<char*>(dataPtr + y * srcBytesPerRow), row.get(), srcBytesPerRow);
    162 
    163         srcRows += srcBytesPerRow;
    164     }
    165 
    166     // Once we are done modifying the data, unlock the bitmap
    167     bitmapDataLock = nullptr;
     259    COMPtr<ID2D1DeviceContext> sourceDeviceContext;
     260    HRESULT hr = platformContext->renderTarget()->QueryInterface(__uuidof(ID2D1DeviceContext), reinterpret_cast<void**>(&sourceDeviceContext));
     261    ASSERT(SUCCEEDED(hr));
     262
     263    if (!sourceDeviceContext)
     264        return nullptr;
     265
     266    COMPtr<ID2D1Bitmap1> sourceCPUBitmap;
     267    D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_CPU_READ | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, Direct2D::pixelFormat());
     268    hr = sourceDeviceContext->CreateBitmap(bitmap->GetPixelSize(), nullptr, bytesPerRow.unsafeGet(), bitmapProperties, &sourceCPUBitmap);
     269    if (!SUCCEEDED(hr))
     270        return nullptr;
     271
     272    if (!sourceCPUBitmap)
     273        return nullptr;
     274
     275    hr = sourceCPUBitmap->CopyFromBitmap(nullptr, bitmap.get(), nullptr);
     276    if (!SUCCEEDED(hr))
     277        return nullptr;
     278
     279    D2D1_MAPPED_RECT mappedSourceData;
     280    hr = sourceCPUBitmap->Map(D2D1_MAP_OPTIONS_READ, &mappedSourceData);
     281    if (!SUCCEEDED(hr))
     282        return nullptr;
     283
     284    COMPtr<ID2D1DeviceContext> targetDeviceContext;
     285    hr = renderTarget->QueryInterface(__uuidof(ID2D1DeviceContext), reinterpret_cast<void**>(&targetDeviceContext));
     286    ASSERT(SUCCEEDED(hr));
     287
     288    COMPtr<ID2D1Bitmap> compatibleBitmap;
     289    hr = targetDeviceContext->CreateBitmap(bitmap->GetPixelSize(), mappedSourceData.bits, mappedSourceData.pitch, Direct2D::bitmapProperties(), &compatibleBitmap);
     290    if (!SUCCEEDED(hr))
     291        return nullptr;
     292
     293    hr = sourceCPUBitmap->Unmap();
     294    ASSERT(SUCCEEDED(hr));
    168295
    169296    context->beginDraw();
     297
     298    return compatibleBitmap;
    170299}
    171300
  • trunk/Source/WebCore/platform/graphics/win/ImageBufferDataDirect2D.h

    r248020 r249110  
    3333#include <wtf/RetainPtr.h>
    3434
     35interface ID2D1RenderTarget;
     36interface ID2D1Bitmap;
     37
    3538namespace WebCore {
    3639
     
    4548    std::unique_ptr<PlatformContextDirect2D> platformContext;
    4649    std::unique_ptr<GraphicsContext> context;
    47     COMPtr<IWICBitmap> bitmapSource;
     50    COMPtr<ID2D1Bitmap> bitmap;
    4851
    4952    RefPtr<Uint8ClampedArray> getData(AlphaPremultiplication, const IntRect&, const IntSize&, bool accelerateRendering, float resolutionScale) const;
    5053    void putData(const Uint8ClampedArray& source, AlphaPremultiplication sourceFormat, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize&, bool accelerateRendering, float resolutionScale);
     54
     55    COMPtr<ID2D1Bitmap> compatibleBitmap(ID2D1RenderTarget*);
    5156};
    5257
  • trunk/Source/WebCore/platform/graphics/win/ImageBufferDirect2D.cpp

    r248846 r249110  
    3939#include "NotImplemented.h"
    4040#include "PlatformContextDirect2D.h"
    41 #include <d2d1.h>
     41#include <d2d1_1.h>
    4242#include <math.h>
    4343#include <wincodec.h>
     
    7777}
    7878
    79 ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpace /*colorSpace*/, RenderingMode renderingMode, const HostWindow*, const GraphicsContext*, bool& success)
     79ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpace /*colorSpace*/, RenderingMode renderingMode, const HostWindow*, const GraphicsContext* targetContext, bool& success)
    8080    : m_logicalSize(size)
    8181    , m_resolutionScale(resolutionScale)
     
    102102        return;
    103103
    104     m_data.data = Vector<char>(numBytes.unsafeGet(), 0);
    105 
    106     m_data.bitmapSource = Direct2D::createDirect2DImageSurfaceWithData(m_data.data.data(), m_size, m_data.bytesPerRow.unsafeGet());
    107     if (!m_data.bitmapSource)
    108         return;
    109 
    110     COMPtr<ID2D1RenderTarget> bitmapContext = Direct2D::createRenderTargetFromWICBitmap(m_data.bitmapSource.get());
     104    auto* platformContext = targetContext ? targetContext->platformContext() : nullptr;
     105    auto* renderTarget = platformContext ? platformContext->renderTarget() : nullptr;
     106
     107    if (!renderTarget)
     108        renderTarget = GraphicsContext::defaultRenderTarget();
     109
     110    D2D1_SIZE_F desiredSize = FloatSize(m_logicalSize);
     111    D2D1_SIZE_U pixelSize = IntSize(m_logicalSize);
     112
     113    auto bitmapContext = Direct2D::createBitmapRenderTargetOfSize(m_logicalSize, renderTarget);
    111114    if (!bitmapContext)
    112115        return;
    113116
    114     // Note: This places the bitmapcontext into a locked state because of the BeginDraw call in the constructor.
     117    HRESULT hr = bitmapContext->GetBitmap(&m_data.bitmap);
     118    if (!SUCCEEDED(hr))
     119        return;
     120
    115121    m_data.platformContext = makeUnique<PlatformContextDirect2D>(bitmapContext.get());
    116122    m_data.context = makeUnique<GraphicsContext>(m_data.platformContext.get(), GraphicsContext::BitmapRenderingContextType::GPUMemory);
     
    141147}
    142148
    143 static COMPtr<IWICBitmap> createCroppedImageIfNecessary(IWICBitmap* image, const IntSize& bounds)
     149static COMPtr<ID2D1Bitmap> createCroppedImageIfNecessary(ID2D1BitmapRenderTarget* bitmapTarget, ID2D1Bitmap* image, const IntSize& bounds)
    144150{
    145151    FloatSize imageSize = image ? nativeImageSize(image) : FloatSize();
    146152
    147153    if (image && (static_cast<size_t>(imageSize.width()) != static_cast<size_t>(bounds.width()) || static_cast<size_t>(imageSize.height()) != static_cast<size_t>(bounds.height()))) {
    148         D2D_POINT_2U origin = { };
    149         WICRect croppedDimensions = { 0, 0, bounds.width(), bounds.height() };
    150 
    151         COMPtr<IWICBitmapClipper> bitmapClipper;
    152         HRESULT hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmapClipper(&bitmapClipper);
    153         if (SUCCEEDED(hr)) {
    154             hr = bitmapClipper->Initialize(image, &croppedDimensions);
    155             if (SUCCEEDED(hr)) {
    156                 COMPtr<IWICBitmap> croppedBitmap;
    157                 hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmapFromSource(image, WICBitmapNoCache, &croppedBitmap);
    158                 if (SUCCEEDED(hr))
    159                     return croppedBitmap;
    160             }
     154        COMPtr<ID2D1Bitmap> croppedBitmap = Direct2D::createBitmap(bitmapTarget, bounds);
     155        if (croppedBitmap) {
     156            auto sourceRect = D2D1::RectU(0, 0, bounds.width(), bounds.height());
     157            HRESULT hr = croppedBitmap->CopyFromBitmap(nullptr, image, &sourceRect);
     158            if (SUCCEEDED(hr))
     159                return croppedBitmap;
    161160        }
    162161    }
     
    165164}
    166165
    167 static RefPtr<Image> createBitmapImageAfterScalingIfNeeded(COMPtr<IWICBitmap>&& image, IntSize internalSize, IntSize logicalSize, IntSize backingStoreSize, float resolutionScale, PreserveResolution preserveResolution)
     166static RefPtr<Image> createBitmapImageAfterScalingIfNeeded(ID2D1BitmapRenderTarget* bitmapTarget, COMPtr<ID2D1Bitmap>&& image, IntSize internalSize, IntSize logicalSize, IntSize backingStoreSize, float resolutionScale, PreserveResolution preserveResolution)
    168167{
    169168    if (resolutionScale == 1 || preserveResolution == PreserveResolution::Yes)
    170         image = createCroppedImageIfNecessary(image.get(), internalSize);
     169        image = createCroppedImageIfNecessary(bitmapTarget, image.get(), internalSize);
    171170    else {
    172171        // FIXME: Need to implement scaled version
     
    182181RefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, PreserveResolution preserveResolution) const
    183182{
    184     COMPtr<IWICBitmap> image;
     183    COMPtr<ID2D1Bitmap> image;
    185184    if (m_resolutionScale == 1 || preserveResolution == PreserveResolution::Yes)
    186185        image = copyNativeImage(copyBehavior);
     
    188187        image = copyNativeImage(DontCopyBackingStore);
    189188
    190     return createBitmapImageAfterScalingIfNeeded(WTFMove(image), internalSize(), logicalSize(), m_data.backingStoreSize, m_resolutionScale, preserveResolution);
     189    auto bitmapTarget = reinterpret_cast<ID2D1BitmapRenderTarget*>(context().platformContext());
     190    return createBitmapImageAfterScalingIfNeeded(bitmapTarget, WTFMove(image), internalSize(), logicalSize(), m_data.backingStoreSize, m_resolutionScale, preserveResolution);
    191191}
    192192
     
    198198    float resolutionScale = imageBuffer->m_resolutionScale;
    199199
    200     return createBitmapImageAfterScalingIfNeeded(sinkIntoNativeImage(WTFMove(imageBuffer)), internalSize, logicalSize, backingStoreSize, resolutionScale, preserveResolution);
     200    auto bitmapTarget = reinterpret_cast<ID2D1BitmapRenderTarget*>(imageBuffer->context().platformContext()->renderTarget());
     201    return createBitmapImageAfterScalingIfNeeded(bitmapTarget, sinkIntoNativeImage(WTFMove(imageBuffer)), internalSize, logicalSize, backingStoreSize, resolutionScale, preserveResolution);
    201202}
    202203
     
    206207}
    207208
    208 COMPtr<IWICBitmap> ImageBuffer::sinkIntoNativeImage(std::unique_ptr<ImageBuffer> imageBuffer)
     209COMPtr<ID2D1Bitmap> ImageBuffer::sinkIntoNativeImage(std::unique_ptr<ImageBuffer> imageBuffer)
    209210{
    210211    // FIXME: See if we can reuse the on-hardware image.
     
    212213}
    213214
    214 COMPtr<IWICBitmap> ImageBuffer::copyNativeImage(BackingStoreCopy copyBehavior) const
    215 {
     215COMPtr<ID2D1Bitmap> ImageBuffer::copyNativeImage(BackingStoreCopy copyBehavior) const
     216{
     217    auto bitmapTarget = reinterpret_cast<ID2D1BitmapRenderTarget*>(context().platformContext());
     218
     219    COMPtr<ID2D1Bitmap> image;
     220    HRESULT hr = bitmapTarget->GetBitmap(&image);
     221    ASSERT(SUCCEEDED(hr));
     222
    216223    // FIXME: m_data.data is nullptr even when asking to copy backing store leading to test failures.
    217224    if (copyBehavior == CopyBackingStore && m_data.data.isEmpty())
     
    222229        return nullptr;
    223230
    224     HRESULT hr = S_OK;
    225     COMPtr<IWICBitmap> image;
    226231    if (!context().isAcceleratedContext()) {
    227232        switch (copyBehavior) {
    228233        case DontCopyBackingStore:
    229             hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmapFromSource(m_data.bitmapSource.get(), WICBitmapNoCache, &image);
    230234            break;
    231235        case CopyBackingStore:
    232             hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmapFromSource(m_data.bitmapSource.get(), WICBitmapCacheOnDemand, &image);
     236            D2D1_RECT_U backingStoreDimenstions = IntRect(IntPoint(), m_data.backingStoreSize);
     237            image->CopyFromMemory(&backingStoreDimenstions, m_data.data.data(), 32);
    233238            break;
    234239        default:
     
    255260    adjustedSrcRect.scale(m_resolutionScale, m_resolutionScale);
    256261
    257     FloatSize currentImageSize = nativeImageSize(m_data.bitmapSource);
    258 
    259     // You can't convert a IWICBitmap to a ID2D1Bitmap with an active GraphicsContext attached to it.
    260     m_data.context->endDraw();
    261 
    262     destContext.drawNativeImage(m_data.bitmapSource, currentImageSize, destRect, adjustedSrcRect, op, blendMode);
    263 
    264     m_data.context->beginDraw();
    265 
    266     destContext.flush();
     262    auto compatibleBitmap = m_data.compatibleBitmap(destContext.platformContext()->renderTarget());
     263
     264    FloatSize currentImageSize = nativeImageSize(compatibleBitmap);
     265    if (currentImageSize.isZero())
     266        return;
     267
     268    destContext.drawNativeImage(compatibleBitmap, currentImageSize, destRect, adjustedSrcRect, op, blendMode);
    267269}
    268270
  • trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp

    r248907 r249110  
    240240        return nullptr;
    241241
     242    if (!m_renderTarget)
     243        return nullptr;
     244
    242245    COMPtr<IWICBitmapFrameDecode> frame;
    243246    HRESULT hr = m_nativeDecoder->GetFrame(0, &frame);
     
    254257        return nullptr;
    255258
    256     COMPtr<IWICBitmap> bitmap;
    257     hr = systemImagingFactory()->CreateBitmapFromSource(converter.get(), WICBitmapCacheOnDemand, &bitmap);
     259    COMPtr<IWICBitmap> wicBitmap;
     260    hr = systemImagingFactory()->CreateBitmapFromSource(converter.get(), WICBitmapCacheOnDemand, &wicBitmap);
     261    if (!SUCCEEDED(hr))
     262        return nullptr;
     263
     264    COMPtr<ID2D1Bitmap> bitmap;
     265    hr = m_renderTarget->CreateBitmapFromWicBitmap(wicBitmap.get(), &bitmap);
    258266    if (!SUCCEEDED(hr))
    259267        return nullptr;
     
    287295    // Image was valid.
    288296}
     297
    289298}
    290299
  • trunk/Source/WebCore/platform/graphics/win/NativeImageDirect2D.cpp

    r248657 r249110  
    5757        return { };
    5858
    59     HRESULT hr = image->GetSize(&width, &height);
    60     if (!SUCCEEDED(hr))
    61         return { };
    62 
    63     return IntSize(width, height);
     59    return image->GetPixelSize();
    6460}
    6561
     
    6965        return false;
    7066
    71     WICPixelFormatGUID pixelFormatGUID = { };
    72     HRESULT hr = image->GetPixelFormat(&pixelFormatGUID);
    73     if (!SUCCEEDED(hr))
    74         return false;
    75 
    76     // FIXME: Should we just check the pixelFormatGUID for relevant ID's we use?
    77 
    78     COMPtr<IWICComponentInfo> componentInfo;
    79     hr = imagingFactory()->CreateComponentInfo(pixelFormatGUID, &componentInfo);
    80     if (!SUCCEEDED(hr))
    81         return false;
    82 
    83     COMPtr<IWICPixelFormatInfo> pixelFormatInfo(Query, componentInfo.get());
    84     if (!pixelFormatInfo)
    85         return false;
    86 
    87     UINT channelCount = 0;
    88     hr = pixelFormatInfo->GetChannelCount(&channelCount);
    89     if (!SUCCEEDED(hr))
    90         return false;
    91 
    92     return channelCount > 3;
     67    D2D1_PIXEL_FORMAT pixelFormat = image->GetPixelFormat();
     68    return pixelFormat.alphaMode != D2D1_ALPHA_MODE_IGNORE;
    9369}
    9470
     
    11793    float opacity = 1.0f;
    11894
    119     COMPtr<ID2D1Bitmap> bitmap;
    120     HRESULT hr = platformContext->renderTarget()->CreateBitmapFromWicBitmap(image.get(), &bitmap);
    121     if (!SUCCEEDED(hr))
    122         return;
    123 
    124     platformContext->renderTarget()->DrawBitmap(bitmap.get(), destRect, opacity, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, adjustedSrcRect);
    125     context.flush();
     95    platformContext->renderTarget()->DrawBitmap(image.get(), destRect, opacity, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, adjustedSrcRect);
    12696}
    12797
  • trunk/Source/WebCore/platform/graphics/win/PatternDirect2D.cpp

    r248020 r249110  
    6060    auto nativeImage = patternImage.nativeImage(nullptr);
    6161
    62     COMPtr<ID2D1Bitmap> bitmap;
    63     HRESULT hr = context.renderTarget()->CreateBitmapFromWicBitmap(nativeImage.get(), &bitmap);
    64     if (!SUCCEEDED(hr))
    65         return nullptr;
    66 
    6762    ID2D1BitmapBrush* patternBrush = nullptr;
    68     hr = context.renderTarget()->CreateBitmapBrush(bitmap.get(), &bitmapBrushProperties, &brushProperties, &patternBrush);
     63    HRESULT hr = context.renderTarget()->CreateBitmapBrush(nativeImage.get(), &bitmapBrushProperties, &brushProperties, &patternBrush);
    6964    ASSERT(SUCCEEDED(hr));
    7065    return patternBrush;
  • trunk/Source/WebCore/svg/graphics/SVGImage.cpp

    r248846 r249110  
    7070#include "COMPtr.h"
    7171#include "Direct2DUtilities.h"
     72#include "GraphicsContext.h"
    7273#include "ImageDecoderDirect2D.h"
    7374#include "PlatformContextDirect2D.h"
     
    236237        return nullptr;
    237238
    238     COMPtr<IWICBitmap> nativeImage;
    239     HRESULT hr = ImageDecoderDirect2D::systemImagingFactory()->CreateBitmap(rect().width(), rect().height(), GUID_WICPixelFormat32bppPRGBA, WICBitmapCacheOnLoad, &nativeImage);
    240     if (!SUCCEEDED(hr))
    241         return nullptr;
    242 
    243     COMPtr<ID2D1RenderTarget> nativeImageTarget = Direct2D::createRenderTargetFromWICBitmap(nativeImage.get());
     239    ASSERT(targetContext->hasPlatformContext());
     240    auto* renderTarget = targetContext->platformContext()->renderTarget();
     241
     242    IntSize bitmapSize(size().width(), size().height());
     243    auto nativeImageTarget = Direct2D::createBitmapRenderTargetOfSize(bitmapSize, renderTarget, 1.0);
    244244    if (!nativeImageTarget)
    245245        return nullptr;
     
    249249
    250250    draw(localContext, rect(), rect(), CompositeSourceOver, BlendMode::Normal, DecodingMode::Synchronous, ImageOrientation::None);
     251
     252    COMPtr<ID2D1Bitmap> nativeImage;
     253    HRESULT hr = nativeImageTarget->GetBitmap(&nativeImage);
     254    if (!SUCCEEDED(hr))
     255        return nullptr;
     256
     257#if !ASSERT_DISABLED
     258    auto nativeImageSize = nativeImage->GetPixelSize();
     259    ASSERT(nativeImageSize.height = rect().size().height());
     260    ASSERT(nativeImageSize.width = rect().size().width());
     261#endif
    251262
    252263    return nativeImage;
  • trunk/Source/WebKit/ChangeLog

    r249108 r249110  
     12019-08-26  Brent Fulgham  <bfulgham@apple.com>
     2
     3        [FTW] Go back to ID2D1Bitmap as our NativeImage type
     4        https://bugs.webkit.org/show_bug.cgi?id=201122
     5
     6        Reviewed by Alex Christensen.
     7
     8        In Bug 200093 I switched the OS type of NativeImagePtr from ID2D1Bitmap to IWICBitmap.
     9        However, this was an ill-advised approach, because it dramatically harmed performance due
     10        to the heavy use of software rendering.
     11
     12        I originally made this change because I thought this was the only way to get to the backing
     13        bits of the bitmaps, but it turns out that a more recent Direct2D data type (ID2D1Bitmap1)
     14        has the ability to map its memory to CPU-accessible memory, allowing software filter effects.
     15
     16        This patch switches back to the ID2D1Bitap data type, and hooks up the ID2D1Bitmap1 data type
     17        to access the underlying memory of the bitmaps when software filter effects are used.
     18
     19        Reviewed by Alex Christensen.
     20
     21        * Shared/ShareableBitmap.h:
     22        * Shared/win/ShareableBitmapDirect2D.cpp:
     23        * UIProcess/win/BackingStoreDirect2D.cpp:
     24        * WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:
     25
    1262019-08-26  Jiewen Tan  <jiewen_tan@apple.com>
    227
  • trunk/Source/WebKit/Shared/ShareableBitmap.h

    r248755 r249110  
    4141
    4242#if USE(DIRECT2D)
    43 interface IWICBitmap;
     43interface ID2D1Bitmap;
     44interface ID2D1RenderTarget;
    4445
    4546#include <WebCore/COMPtr.h>
     
    132133    RefPtr<cairo_surface_t> createCairoSurface();
    133134#elif USE(DIRECT2D)
    134     COMPtr<IWICBitmap> createDirect2DSurface();
     135    COMPtr<ID2D1Bitmap> createDirect2DSurface(ID2D1RenderTarget*);
    135136    void sync(WebCore::GraphicsContext&);
    136137#endif
     
    163164
    164165#if USE(DIRECT2D)
    165     COMPtr<IWICBitmap> m_bitmap;
     166    COMPtr<ID2D1Bitmap> m_bitmap;
    166167#endif
    167168
     
    170171
    171172    // If the shareable bitmap is backed by fastMalloced memory, this points to the data.
    172     void* m_data;
     173    void* m_data { nullptr };
    173174};
    174175
  • trunk/Source/WebKit/Shared/win/ShareableBitmapDirect2D.cpp

    r248907 r249110  
    3636#include <WebCore/NotImplemented.h>
    3737#include <WebCore/PlatformContextDirect2D.h>
     38#include <d2d1_1.h>
    3839#include <wincodec.h>
    3940#include <wtf/ProcessID.h>
     
    4344using namespace WebCore;
    4445
    45 static const auto bitmapFormat = GUID_WICPixelFormat32bppPBGRA;
    46 
    4746static unsigned strideForWidth(unsigned width)
    4847{
    49     static unsigned bitsPerPixel = Direct2D::bitsPerPixel(bitmapFormat);
     48    static unsigned bitsPerPixel = Direct2D::bitsPerPixel(Direct2D::wicBitmapFormat());
    5049    return bitsPerPixel * width / 8;
    5150}
     
    6968std::unique_ptr<GraphicsContext> ShareableBitmap::createGraphicsContext()
    7069{
    71     m_bitmap = createDirect2DSurface();
    72     COMPtr<ID2D1RenderTarget> bitmapContext = Direct2D::createRenderTargetFromWICBitmap(m_bitmap.get());
     70    auto bitmapContext = Direct2D::createBitmapRenderTargetOfSize(m_size);
     71    if (!bitmapContext)
     72        return nullptr;
     73
     74    HRESULT hr = bitmapContext->GetBitmap(&m_bitmap);
     75    RELEASE_ASSERT(SUCCEEDED(hr));
    7376    return makeUnique<GraphicsContext>(GraphicsContextImplDirect2D::createFactory(bitmapContext.get()));
    7477}
     
    8184void ShareableBitmap::paint(GraphicsContext& context, float scaleFactor, const IntPoint& dstPoint, const IntRect& srcRect)
    8285{
    83     auto surface = createDirect2DSurface();
     86    auto surface = createDirect2DSurface(context.platformContext()->renderTarget());
    8487
    8588#ifndef _NDEBUG
    86     unsigned width, height;
    87     HRESULT hr = surface->GetSize(&width, &height);
    88     ASSERT(width == m_size.width());
    89     ASSERT(height == m_size.height());
     89    auto bitmapSize = surface->GetPixelSize();
     90    ASSERT(bitmapSize.width == m_size.width());
     91    ASSERT(bitmapSize.height == m_size.height());
    9092#endif
    9193
     
    101103}
    102104
    103 COMPtr<IWICBitmap> ShareableBitmap::createDirect2DSurface()
     105COMPtr<ID2D1Bitmap> ShareableBitmap::createDirect2DSurface(ID2D1RenderTarget* renderTarget)
    104106{
    105     m_bitmap = createSurfaceFromData(data(), m_size);
    106     return m_bitmap;
     107    auto bitmapProperties = Direct2D::bitmapProperties();
     108
     109    COMPtr<ID2D1Bitmap> bitmap;
     110    uint32_t stride = 4 * m_size.width();
     111    HRESULT hr = renderTarget->CreateBitmap(m_size, data(), stride, &bitmapProperties, &bitmap);
     112    if (!SUCCEEDED(hr))
     113        return nullptr;
     114
     115    return bitmap;
    107116}
    108117
    109118RefPtr<Image> ShareableBitmap::createImage()
    110119{
    111     auto surface = createDirect2DSurface();
     120    auto surface = createDirect2DSurface(GraphicsContext::defaultRenderTarget());
    112121    if (!surface)
    113122        return nullptr;
     
    122131    graphicsContext.endDraw();
    123132
    124     WICRect rcLock = { 0, 0, m_size.width(), m_size.height() };
     133    COMPtr<ID2D1DeviceContext> d2dDeviceContext;
     134    HRESULT hr = graphicsContext.platformContext()->renderTarget()->QueryInterface(__uuidof(ID2D1DeviceContext), reinterpret_cast<void**>(&d2dDeviceContext));
     135    ASSERT(SUCCEEDED(hr));
    125136
    126     COMPtr<IWICBitmapLock> bitmapDataLock;
    127     HRESULT hr = m_bitmap->Lock(&rcLock, WICBitmapLockRead, &bitmapDataLock);
    128     if (SUCCEEDED(hr)) {
    129         UINT bufferSize = 0;
    130         WICInProcPointer dataPtr = nullptr;
    131         hr = bitmapDataLock->GetDataPointer(&bufferSize, &dataPtr);
    132         if (SUCCEEDED(hr))
    133             memcpy(data(), reinterpret_cast<char*>(dataPtr), bufferSize);
     137    const unsigned stride = strideForWidth(m_size.width());
     138
     139    COMPtr<ID2D1Bitmap1> cpuBitmap;
     140    D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_CPU_READ | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, Direct2D::pixelFormat());
     141    hr = d2dDeviceContext->CreateBitmap(m_size, nullptr, stride, bitmapProperties, &cpuBitmap);
     142    if (!SUCCEEDED(hr))
     143        return;
     144
     145    hr = cpuBitmap->CopyFromBitmap(nullptr, m_bitmap.get(), nullptr);
     146    if (!SUCCEEDED(hr))
     147        return;
     148
     149    D2D1_MAPPED_RECT mappedData;
     150    hr = cpuBitmap->Map(D2D1_MAP_OPTIONS_READ, &mappedData);
     151    if (!SUCCEEDED(hr))
     152        return;
     153
     154    if (mappedData.pitch == stride)
     155        memcpy(data(), reinterpret_cast<char*>(mappedData.bits), stride * m_size.height());
     156    else {
     157        // Stride is different, so must do a rowwise copy:
     158        Checked<int> height = m_size.height();
     159        Checked<int> width = m_size.width();
     160
     161        const uint8_t* srcRows = mappedData.bits;
     162        uint8_t* row = reinterpret_cast<uint8_t*>(data());
     163
     164        for (int y = 0; y < height.unsafeGet(); ++y) {
     165            for (int x = 0; x < width.unsafeGet(); x++) {
     166                int basex = x * 4;
     167                reinterpret_cast<uint32_t*>(row + basex)[0] = reinterpret_cast<const uint32_t*>(srcRows + basex)[0];
     168            }
     169
     170            srcRows += mappedData.pitch;
     171            row += stride;
     172        }
    134173    }
    135174
    136     // Once we are done modifying the data, unlock the bitmap
    137     bitmapDataLock = nullptr;
     175    hr = cpuBitmap->Unmap();
     176    ASSERT(SUCCEEDED(hr));
    138177}
    139178
  • trunk/Source/WebKit/UIProcess/win/BackingStoreDirect2D.cpp

    r248907 r249110  
    7474    IntPoint updateRectBoundsLocation = updateInfo.updateRectBounds.location();
    7575
    76     auto updateWICBitmap = bitmap->createDirect2DSurface();
    77 
    78     HRESULT hr = S_OK;
    79 #ifndef _NDEBUG
    80     unsigned width, height;
    81     hr = updateWICBitmap->GetSize(&width, &height);
    82     ASSERT(width == updateInfo.updateRectBounds.width());
    83     ASSERT(height == updateInfo.updateRectBounds.height());
    84 #endif
    85 
    86     COMPtr<ID2D1Bitmap> deviceUpdateBitmap;
    87     hr = m_backend->renderTarget()->CreateBitmapFromWicBitmap(updateWICBitmap.get(), &deviceUpdateBitmap);
    88     if (!SUCCEEDED(hr))
    89         return;
     76    COMPtr<ID2D1Bitmap> deviceUpdateBitmap = bitmap->createDirect2DSurface(m_backend->renderTarget());
    9077
    9178#ifndef _NDEBUG
  • trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp

    r248846 r249110  
    755755
    756756#if USE(DIRECT2D)
    757     bitmap->sync(*graphicsContext);
     757    if (graphicsContext)
     758        bitmap->sync(*graphicsContext);
    758759#endif
    759760
Note: See TracChangeset for help on using the changeset viewer.