Changeset 224195 in webkit


Ignore:
Timestamp:
Oct 30, 2017 12:34:42 PM (6 years ago)
Author:
dino@apple.com
Message:

Implement "bitmaprenderer" CanvasRenderingContext
https://bugs.webkit.org/show_bug.cgi?id=178992
<rdar://problem/34147157>

Reviewed by Sam Weinig.

LayoutTests/imported/w3c:

Update the expected results now more of the interface has
been added.

  • web-platform-tests/imagebitmap-renderingcontext/bitmaprenderer-as-imagesource-expected.txt:
  • web-platform-tests/imagebitmap-renderingcontext/context-creation-with-alpha-expected.txt:
  • web-platform-tests/imagebitmap-renderingcontext/tranferFromImageBitmap-null-expected.txt:
  • web-platform-tests/imagebitmap-renderingcontext/transferFromImageBitmap-detached-expected.txt:

Source/WebCore:

Implement the "bitmaprenderer" context for HTMLCanvasElement.
Use as much of the existing 2d context code as possible, which
means that we are painting the ImageBitmap into the backing
store. This isn't optimal, but it is good enough to get
going while we move buffer ownership from the canvas object
into the rendering contexts.

This patch raised a few issues on the HTML specification:
https://github.com/whatwg/html/issues/3164
https://github.com/whatwg/html/issues/3165
https://github.com/whatwg/html/issues/3166
https://github.com/whatwg/html/issues/3167

Update existing Web Platform Test results.

  • html/HTMLCanvasElement.cpp:

(WebCore::HTMLCanvasElement::createContext2d): Drive-by comment fix.
(WebCore::HTMLCanvasElement::createContextWebGL): Ditto.
(WebCore::HTMLCanvasElement::createContextWebGPU): Ditto.
(WebCore::HTMLCanvasElement::createContextBitmapRenderer): We now require
a layer/backing store for a bitmap context.
(WebCore::HTMLCanvasElement::paintsIntoCanvasBuffer const): Add bitmap-renderer
to the type of context that uses the canvas's backing store.
(WebCore::HTMLCanvasElement::createImageBuffer const): Comment fix.
(WebCore::HTMLCanvasElement::setImageBuffer const): Change parameter to a &&.
(WebCore::HTMLCanvasElement::setImageBufferAndMarkDirty): New function to set
the backing store efficiently, as well as make it look like we need to repaint
the entire canvas.
(WebCore::HTMLCanvasElement::drawingContext const): The buffer doesn't actually
need to provide a GraphicsContext if we're a bitmap renderer.

  • html/HTMLCanvasElement.h:
  • html/ImageBitmap.cpp:

(WebCore::ImageBitmap::transferOwnershipAndClose): New helper to give the ownership
of the ImageBuffer away, and look like close() was called.

  • html/ImageBitmap.h:
  • html/canvas/ImageBitmapRenderingContext.cpp: Implement the algorithm from the HTML

specification.
(WebCore::ImageBitmapRenderingContext::ImageBitmapRenderingContext):
(WebCore::ImageBitmapRenderingContext::isAccelerated const):
(WebCore::ImageBitmapRenderingContext::setOutputBitmap):
(WebCore::ImageBitmapRenderingContext::transferFromImageBitmap):

  • html/canvas/ImageBitmapRenderingContext.h:
  • html/canvas/ImageBitmapRenderingContext.idl:
Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r224166 r224195  
     12017-10-30  Dean Jackson  <dino@apple.com>
     2
     3        Implement "bitmaprenderer" CanvasRenderingContext
     4        https://bugs.webkit.org/show_bug.cgi?id=178992
     5        <rdar://problem/34147157>
     6
     7        Reviewed by Sam Weinig.
     8
     9        Update the expected results now more of the interface has
     10        been added.
     11
     12        * web-platform-tests/imagebitmap-renderingcontext/bitmaprenderer-as-imagesource-expected.txt:
     13        * web-platform-tests/imagebitmap-renderingcontext/context-creation-with-alpha-expected.txt:
     14        * web-platform-tests/imagebitmap-renderingcontext/tranferFromImageBitmap-null-expected.txt:
     15        * web-platform-tests/imagebitmap-renderingcontext/transferFromImageBitmap-detached-expected.txt:
     16
    1172017-10-29  Chris Dumez  <cdumez@apple.com>
    218
  • trunk/LayoutTests/imported/w3c/web-platform-tests/imagebitmap-renderingcontext/bitmaprenderer-as-imagesource-expected.txt

    r224158 r224195  
    11
    2 FAIL Test that createImageBitmap from a bitmaprenderer canvas produces correct result myCtx.transferFromImageBitmap is not a function. (In 'myCtx.transferFromImageBitmap(image)', 'myCtx.transferFromImageBitmap' is undefined)
     2FAIL Test that createImageBitmap from a bitmaprenderer canvas produces correct result assert_equals: expected 10 but got 20
    33PASS Test that createImageBitmap on a bitmaprenderer canvas that never consumes any source produces correct result
    4 FAIL Test that createImageBitmap on a bitmaprenderer canvas that consumes null produces correct result ctx.transferFromImageBitmap is not a function. (In 'ctx.transferFromImageBitmap(null)', 'ctx.transferFromImageBitmap' is undefined)
     4PASS Test that createImageBitmap on a bitmaprenderer canvas that consumes null produces correct result
    55
  • trunk/LayoutTests/imported/w3c/web-platform-tests/imagebitmap-renderingcontext/context-creation-with-alpha-expected.txt

    r223775 r224195  
    11
    2 FAIL Test that an ImageBitmapRenderingContext with alpha disabled makes the canvas opaque promise_test: Unhandled rejection with value: object "TypeError: dstCtx.transferFromImageBitmap is not a function. (In 'dstCtx.transferFromImageBitmap(image)', 'dstCtx.transferFromImageBitmap' is undefined)"
    3 FAIL Test that an ImageBitmapRenderingContext with alpha enabled preserves the alpha promise_test: Unhandled rejection with value: object "TypeError: dstCtx.transferFromImageBitmap is not a function. (In 'dstCtx.transferFromImageBitmap(image)', 'dstCtx.transferFromImageBitmap' is undefined)"
    4 FAIL Test that the 'alpha' context creation attribute is true by default promise_test: Unhandled rejection with value: object "TypeError: dstCtx.transferFromImageBitmap is not a function. (In 'dstCtx.transferFromImageBitmap(image)', 'dstCtx.transferFromImageBitmap' is undefined)"
     2FAIL Test that an ImageBitmapRenderingContext with alpha disabled makes the canvas opaque assert_array_equals: property 1, expected 127 but got 255
     3PASS Test that an ImageBitmapRenderingContext with alpha enabled preserves the alpha
     4PASS Test that the 'alpha' context creation attribute is true by default
    55
  • trunk/LayoutTests/imported/w3c/web-platform-tests/imagebitmap-renderingcontext/tranferFromImageBitmap-null-expected.txt

    r223775 r224195  
    11
    2 FAIL Test that transferFromImageBitmap(null) discards the previously transferred image promise_test: Unhandled rejection with value: object "TypeError: bitmapCtx.transferFromImageBitmap is not a function. (In 'bitmapCtx.transferFromImageBitmap(greenImage)', 'bitmapCtx.transferFromImageBitmap' is undefined)"
     2PASS Test that transferFromImageBitmap(null) discards the previously transferred image
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/imagebitmap-renderingcontext/transferFromImageBitmap-detached-expected.txt

    r223775 r224195  
    11
    2 FAIL Test transferFromImageBitmap(image) with a detached image should throw InvalidStateError promise_test: Unhandled rejection with value: object "TypeError: dstCtx.transferFromImageBitmap is not a function. (In 'dstCtx.transferFromImageBitmap(image)', 'dstCtx.transferFromImageBitmap' is undefined)"
     2PASS Test transferFromImageBitmap(image) with a detached image should throw InvalidStateError
    33
  • trunk/Source/WebCore/ChangeLog

    r224193 r224195  
     12017-10-30  Dean Jackson  <dino@apple.com>
     2
     3        Implement "bitmaprenderer" CanvasRenderingContext
     4        https://bugs.webkit.org/show_bug.cgi?id=178992
     5        <rdar://problem/34147157>
     6
     7        Reviewed by Sam Weinig.
     8
     9        Implement the "bitmaprenderer" context for HTMLCanvasElement.
     10        Use as much of the existing 2d context code as possible, which
     11        means that we are painting the ImageBitmap into the backing
     12        store. This isn't optimal, but it is good enough to get
     13        going while we move buffer ownership from the canvas object
     14        into the rendering contexts.
     15
     16        This patch raised a few issues on the HTML specification:
     17        https://github.com/whatwg/html/issues/3164
     18        https://github.com/whatwg/html/issues/3165
     19        https://github.com/whatwg/html/issues/3166
     20        https://github.com/whatwg/html/issues/3167
     21
     22        Update existing Web Platform Test results.
     23
     24        * html/HTMLCanvasElement.cpp:
     25        (WebCore::HTMLCanvasElement::createContext2d): Drive-by comment fix.
     26        (WebCore::HTMLCanvasElement::createContextWebGL): Ditto.
     27        (WebCore::HTMLCanvasElement::createContextWebGPU): Ditto.
     28        (WebCore::HTMLCanvasElement::createContextBitmapRenderer): We now require
     29        a layer/backing store for a bitmap context.
     30        (WebCore::HTMLCanvasElement::paintsIntoCanvasBuffer const): Add bitmap-renderer
     31        to the type of context that uses the canvas's backing store.
     32        (WebCore::HTMLCanvasElement::createImageBuffer const): Comment fix.
     33        (WebCore::HTMLCanvasElement::setImageBuffer const): Change parameter to a &&.
     34        (WebCore::HTMLCanvasElement::setImageBufferAndMarkDirty): New function to set
     35        the backing store efficiently, as well as make it look like we need to repaint
     36        the entire canvas.
     37        (WebCore::HTMLCanvasElement::drawingContext const): The buffer doesn't actually
     38        need to provide a GraphicsContext if we're a bitmap renderer.
     39        * html/HTMLCanvasElement.h:
     40
     41        * html/ImageBitmap.cpp:
     42        (WebCore::ImageBitmap::transferOwnershipAndClose): New helper to give the ownership
     43        of the ImageBuffer away, and look like close() was called.
     44        * html/ImageBitmap.h:
     45
     46        * html/canvas/ImageBitmapRenderingContext.cpp: Implement the algorithm from the HTML
     47        specification.
     48        (WebCore::ImageBitmapRenderingContext::ImageBitmapRenderingContext):
     49        (WebCore::ImageBitmapRenderingContext::isAccelerated const):
     50        (WebCore::ImageBitmapRenderingContext::setOutputBitmap):
     51        (WebCore::ImageBitmapRenderingContext::transferFromImageBitmap):
     52        * html/canvas/ImageBitmapRenderingContext.h:
     53        * html/canvas/ImageBitmapRenderingContext.idl:
     54
    1552017-10-30  Simon Fraser  <simon.fraser@apple.com>
    256
  • trunk/Source/WebCore/html/HTMLCanvasElement.cpp

    r223644 r224195  
    374374
    375375#if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS)
    376     // Need to make sure a RenderLayer and compositing layer get created for the Canvas
     376    // Need to make sure a RenderLayer and compositing layer get created for the Canvas.
    377377    invalidateStyleAndLayerComposition();
    378378#endif
     
    434434    m_context = WebGLRenderingContextBase::create(*this, attrs, type);
    435435    if (m_context) {
    436         // Need to make sure a RenderLayer and compositing layer get created for the Canvas
     436        // Need to make sure a RenderLayer and compositing layer get created for the Canvas.
    437437        invalidateStyleAndLayerComposition();
    438438
     
    475475    m_context = WebGPURenderingContext::create(*this);
    476476    if (m_context) {
    477         // Need to make sure a RenderLayer and compositing layer get created for the Canvas
     477        // Need to make sure a RenderLayer and compositing layer get created for the Canvas.
    478478        invalidateStyleAndLayerComposition();
    479479
     
    505505}
    506506
     507// FIXME: Needs to accept ImageBitmapRenderingContext::Settings.
    507508ImageBitmapRenderingContext* HTMLCanvasElement::createContextBitmapRenderer(const String& type)
    508509{
     
    511512
    512513    m_context = std::make_unique<ImageBitmapRenderingContext>(*this);
     514
     515#if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS)
     516    // Need to make sure a RenderLayer and compositing layer get created for the Canvas.
     517    invalidateStyleAndLayerComposition();
     518#endif
    513519
    514520    return static_cast<ImageBitmapRenderingContext*>(m_context.get());
     
    603609    ASSERT(m_context);
    604610#if USE(IOSURFACE_CANVAS_BACKING_STORE)
    605     if (m_context->is2d())
     611    if (m_context->is2d() || m_context->isBitmapRenderer())
    606612        return true;
    607613#endif
     
    957963
    958964#if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS)
    959     if (m_context && m_context->is2d())
     965    if (m_context && m_context->is2d()) {
    960966        // Recalculate compositing requirements if acceleration state changed.
    961967        const_cast<HTMLCanvasElement*>(this)->invalidateStyleAndLayerComposition();
    962 #endif
    963 }
    964 
    965 void HTMLCanvasElement::setImageBuffer(std::unique_ptr<ImageBuffer> buffer) const
     968    }
     969#endif
     970}
     971
     972void HTMLCanvasElement::setImageBuffer(std::unique_ptr<ImageBuffer>&& buffer) const
    966973{
    967974    size_t previousMemoryCost = memoryCost();
     
    980987}
    981988
     989void HTMLCanvasElement::setImageBufferAndMarkDirty(std::unique_ptr<ImageBuffer>&& buffer)
     990{
     991    m_hasCreatedImageBuffer = true;
     992    setImageBuffer(WTFMove(buffer));
     993    didDraw(FloatRect(FloatPoint(), m_size));
     994}
     995
    982996GraphicsContext* HTMLCanvasElement::drawingContext() const
    983997{
     998    if (m_context && !m_context->is2d())
     999        return nullptr;
     1000
    9841001    return buffer() ? &m_imageBuffer->context() : nullptr;
    9851002}
  • trunk/Source/WebCore/html/HTMLCanvasElement.h

    r223728 r224195  
    151151
    152152    SecurityOrigin* securityOrigin() const;
     153    void setOriginClean() { m_originClean = true; }
    153154    void setOriginTainted() { m_originClean = false; }
    154155    bool originClean() const { return m_originClean; }
     
    169170    size_t externalMemoryCost() const;
    170171
     172    // FIXME: Only some canvas rendering contexts need an ImageBuffer.
     173    // It would be better to have the contexts own the buffers.
     174    void setImageBufferAndMarkDirty(std::unique_ptr<ImageBuffer>&&);
     175
    171176private:
    172177    HTMLCanvasElement(const QualifiedName&, Document&);
     
    184189
    185190    void setSurfaceSize(const IntSize&);
    186     void setImageBuffer(std::unique_ptr<ImageBuffer>) const;
     191    void setImageBuffer(std::unique_ptr<ImageBuffer>&&) const;
    187192    void releaseImageBufferAndContext();
    188193
  • trunk/Source/WebCore/html/ImageBitmap.cpp

    r224158 r224195  
    4949namespace WebCore {
    5050
    51 #if PLATFORM(COCOA) && !PLATFORM(IOS_SIMULATOR)
     51#if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS)
    5252static RenderingMode bufferRenderingMode = Accelerated;
    5353#else
    5454static RenderingMode bufferRenderingMode = Unaccelerated;
    5555#endif
    56 
    5756
    5857Ref<ImageBitmap> ImageBitmap::create()
     
    560559}
    561560
    562 }
     561std::unique_ptr<ImageBuffer> ImageBitmap::transferOwnershipAndClose()
     562{
     563    m_detached = true;
     564    return WTFMove(m_bitmapData);
     565}
     566
     567}
  • trunk/Source/WebCore/html/ImageBitmap.h

    r223925 r224195  
    7575    bool originClean() const { return m_originClean; }
    7676
     77    std::unique_ptr<ImageBuffer> transferOwnershipAndClose();
     78
    7779private:
    7880    friend class PendingImageBitmap;
  • trunk/Source/WebCore/html/canvas/ImageBitmapRenderingContext.cpp

    r222997 r224195  
    2727#include "ImageBitmapRenderingContext.h"
    2828
     29#include "ImageBitmap.h"
     30#include "ImageBuffer.h"
     31
    2932namespace WebCore {
     33
     34#if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS)
     35static RenderingMode bufferRenderingMode = Accelerated;
     36#else
     37static RenderingMode bufferRenderingMode = Unaccelerated;
     38#endif
    3039
    3140ImageBitmapRenderingContext::ImageBitmapRenderingContext(HTMLCanvasElement& canvas)
    3241    : CanvasRenderingContext(canvas)
    3342{
     43    setOutputBitmap(nullptr);
     44}
     45
     46ImageBitmapRenderingContext::~ImageBitmapRenderingContext() = default;
     47
     48bool ImageBitmapRenderingContext::isAccelerated() const
     49{
     50    return bufferRenderingMode == Accelerated;
     51}
     52
     53void ImageBitmapRenderingContext::setOutputBitmap(RefPtr<ImageBitmap> imageBitmap)
     54{
     55    // 1. If a bitmap argument was not provided, then:
     56
     57    if (!imageBitmap) {
     58
     59        // 1.1. Set context's bitmap mode to blank.
     60
     61        m_bitmapMode = BitmapMode::Blank;
     62
     63        // 1.2. Let canvas be the canvas element to which context is bound.
     64
     65        // 1.3. Set context's output bitmap to be transparent black with an
     66        //      intrinsic width equal to the numeric value of canvas's width attribute
     67        //      and an intrinsic height equal to the numeric value of canvas's height
     68        //      attribute, those values being interpreted in CSS pixels.
     69
     70        // FIXME: What is the point of creating a full size transparent buffer that
     71        // can never be changed? Wouldn't a 1x1 buffer give the same rendering? The
     72        // only reason I can think of is toDataURL(), but that doesn't seem like
     73        // a good enough argument to waste memory.
     74
     75        canvas().setImageBufferAndMarkDirty(ImageBuffer::create(FloatSize(canvas().width(), canvas().height()), bufferRenderingMode));
     76
     77        // 1.4. Set the output bitmap's origin-clean flag to true.
     78
     79        canvas().setOriginClean();
     80        return;
     81    }
     82
     83    // 2. If a bitmap argument was provided, then:
     84
     85    // 2.1. Set context's bitmap mode to valid.
     86
     87    m_bitmapMode = BitmapMode::Valid;
     88
     89    // 2.2. Set context's output bitmap to refer to the same underlying
     90    //      bitmap data as bitmap, without making a copy.
     91    //      Note: the origin-clean flag of bitmap is included in the
     92    //      bitmap data to be referenced by context's output bitmap.
     93
     94    if (imageBitmap->originClean())
     95        canvas().setOriginClean();
     96    else
     97        canvas().setOriginTainted();
     98    canvas().setImageBufferAndMarkDirty(imageBitmap->transferOwnershipAndClose());
     99}
     100
     101ExceptionOr<void> ImageBitmapRenderingContext::transferFromImageBitmap(RefPtr<ImageBitmap> imageBitmap)
     102{
     103    // 1. Let bitmapContext be the ImageBitmapRenderingContext object on which
     104    //    the transferFromImageBitmap() method was called.
     105
     106    // 2. If imageBitmap is null, then run the steps to set an ImageBitmapRenderingContext's
     107    //    output bitmap, with bitmapContext as the context argument and no bitmap argument,
     108    //    then abort these steps.
     109
     110    if (!imageBitmap) {
     111        setOutputBitmap(nullptr);
     112        return { };
     113    }
     114
     115    // 3. If the value of imageBitmap's [[Detached]] internal slot is set to true,
     116    //    then throw an "InvalidStateError" DOMException and abort these steps.
     117
     118    if (imageBitmap->isDetached())
     119        return Exception { InvalidStateError };
     120
     121    // 4. Run the steps to set an ImageBitmapRenderingContext's output bitmap,
     122    //    with the context argument equal to bitmapContext, and the bitmap
     123    //    argument referring to imageBitmap's underlying bitmap data.
     124
     125    setOutputBitmap(imageBitmap);
     126
     127    // 5. Set the value of imageBitmap's [[Detached]] internal slot to true.
     128    // 6. Unset imageBitmap's bitmap data.
     129
     130    // Note that the algorithm in the specification is currently a bit
     131    // muddy here. The setOutputBitmap step above had to transfer ownership
     132    // from the imageBitmap to this object, which requires a detach and unset,
     133    // so this step isn't necessary, but we'll do it anyway.
     134
     135    imageBitmap->close();
     136
     137    return { };
    34138}
    35139
  • trunk/Source/WebCore/html/canvas/ImageBitmapRenderingContext.h

    r222997 r224195  
    2828#include "CanvasRenderingContext.h"
    2929
     30#include "ExceptionOr.h"
     31#include "ImageBufferData.h"
     32#include <wtf/RefPtr.h>
     33
    3034namespace WebCore {
     35
     36class ImageBitmap;
     37class ImageBuffer;
    3138
    3239class ImageBitmapRenderingContext final : public CanvasRenderingContext {
     
    3643    };
    3744
     45    enum class BitmapMode {
     46        Valid,
     47        Blank
     48    };
     49
    3850    ImageBitmapRenderingContext(HTMLCanvasElement&);
     51    ~ImageBitmapRenderingContext();
     52
     53    ExceptionOr<void> transferFromImageBitmap(RefPtr<ImageBitmap>);
     54
     55    BitmapMode bitmapMode() { return m_bitmapMode; }
     56    bool hasAlpha() { return m_settings.alpha; }
    3957
    4058private:
    4159    bool isBitmapRenderer() const final { return true; }
     60    bool isAccelerated() const override;
     61
     62    void setOutputBitmap(RefPtr<ImageBitmap>);
     63
     64    BitmapMode m_bitmapMode { BitmapMode::Blank };
     65    Settings m_settings;
    4266};
    4367
  • trunk/Source/WebCore/html/canvas/ImageBitmapRenderingContext.idl

    r222997 r224195  
    2929    readonly attribute HTMLCanvasElement canvas;
    3030
    31     // FIXME: Add support for transferFromImageBitmap once we have ImageBitmap support.
    32     // void transferFromImageBitmap(ImageBitmap? bitmap);
     31    [MayThrowException] void transferFromImageBitmap(ImageBitmap? bitmap);
    3332};
    3433
Note: See TracChangeset for help on using the changeset viewer.