Changeset 271741 in webkit


Ignore:
Timestamp:
Jan 22, 2021 1:34:10 AM (3 years ago)
Author:
youenn@apple.com
Message:

Validate ItemHandles when decoding them in GPUProcess
https://bugs.webkit.org/show_bug.cgi?id=220710

Reviewed by Wenson Hsieh.

ItemHandle may contain members that need to be validated if they are encoded/decoded through memory copy instead of IPC encode/decode routines.
This is particularly true of identifiers that can be null but cannot be encoded/decoded if the identifier is null.
For these inline ItemHandles, validate them before copying them.
No observable change of behavior, coveredd by existing tests.

  • platform/graphics/displaylists/DisplayList.cpp:

(WebCore::DisplayList::DisplayList::iterator::updateCurrentItem):

  • platform/graphics/displaylists/DisplayListItemBuffer.cpp:

(WebCore::DisplayList::ItemHandleInspector::test):
(WebCore::DisplayList::copyInto):
(WebCore::DisplayList::ItemHandle::safeCopyInto const):
(WebCore::DisplayList::ItemHandle::copyTo const): Deleted.

  • platform/graphics/displaylists/DisplayListItemBuffer.h:
  • platform/graphics/displaylists/DisplayListItems.h:

(WebCore::DisplayList::ClipToImageBuffer::isValid const):
(WebCore::DisplayList::DrawImageBuffer::isValid const):
(WebCore::DisplayList::DrawNativeImage::isValid const):
(WebCore::DisplayList::DrawPattern::isValid const):
(WebCore::DisplayList::PaintFrameForMedia::isValid const):
(WebCore::DisplayList::FlushContext::FlushContext):
(WebCore::DisplayList::FlushContext::isValid const):
(WebCore::DisplayList::MetaCommandChangeItemBuffer::MetaCommandChangeItemBuffer):
(WebCore::DisplayList::MetaCommandChangeItemBuffer::isValid const):
(WebCore::DisplayList::MetaCommandChangeDestinationImageBuffer::MetaCommandChangeDestinationImageBuffer):
(WebCore::DisplayList::MetaCommandChangeDestinationImageBuffer::isValid const):

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r271740 r271741  
     12021-01-22  Youenn Fablet  <youenn@apple.com>
     2
     3        Validate ItemHandles when decoding them in GPUProcess
     4        https://bugs.webkit.org/show_bug.cgi?id=220710
     5
     6        Reviewed by Wenson Hsieh.
     7
     8        ItemHandle may contain members that need to be validated if they are encoded/decoded through memory copy instead of IPC encode/decode routines.
     9        This is particularly true of identifiers that can be null but cannot be encoded/decoded if the identifier is null.
     10        For these inline ItemHandles, validate them before copying them.
     11        No observable change of behavior, coveredd by existing tests.
     12
     13        * platform/graphics/displaylists/DisplayList.cpp:
     14        (WebCore::DisplayList::DisplayList::iterator::updateCurrentItem):
     15        * platform/graphics/displaylists/DisplayListItemBuffer.cpp:
     16        (WebCore::DisplayList::ItemHandleInspector::test):
     17        (WebCore::DisplayList::copyInto):
     18        (WebCore::DisplayList::ItemHandle::safeCopyInto const):
     19        (WebCore::DisplayList::ItemHandle::copyTo const): Deleted.
     20        * platform/graphics/displaylists/DisplayListItemBuffer.h:
     21        * platform/graphics/displaylists/DisplayListItems.h:
     22        (WebCore::DisplayList::ClipToImageBuffer::isValid const):
     23        (WebCore::DisplayList::DrawImageBuffer::isValid const):
     24        (WebCore::DisplayList::DrawNativeImage::isValid const):
     25        (WebCore::DisplayList::DrawPattern::isValid const):
     26        (WebCore::DisplayList::PaintFrameForMedia::isValid const):
     27        (WebCore::DisplayList::FlushContext::FlushContext):
     28        (WebCore::DisplayList::FlushContext::isValid const):
     29        (WebCore::DisplayList::MetaCommandChangeItemBuffer::MetaCommandChangeItemBuffer):
     30        (WebCore::DisplayList::MetaCommandChangeItemBuffer::isValid const):
     31        (WebCore::DisplayList::MetaCommandChangeDestinationImageBuffer::MetaCommandChangeDestinationImageBuffer):
     32        (WebCore::DisplayList::MetaCommandChangeDestinationImageBuffer::isValid const):
     33
    1342021-01-19  Nikolas Zimmermann  <nzimmermann@igalia.com>
    235
  • trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.cpp

    r270796 r271741  
    363363        m_currentItemSizeInBuffer = 2 * sizeof(uint64_t) + roundUpToMultipleOf(alignof(uint64_t), dataLength);
    364364    } else {
    365         ItemHandle { m_cursor }.copyTo({ m_currentBufferForItem });
     365        if (!ItemHandle { m_cursor }.safeCopy({ m_currentBufferForItem })) {
     366            // FIXME: Instead of crashing, this needs to fail gracefully and inform the caller.
     367            RELEASE_ASSERT_NOT_REACHED();
     368        }
    366369        m_currentItemSizeInBuffer = paddedSizeOfTypeAndItem;
    367370    }
  • trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemBuffer.cpp

    r270796 r271741  
    540540}
    541541
    542 void ItemHandle::copyTo(ItemHandle destination) const
     542template<typename, typename = void> inline constexpr bool HasIsValid = false;
     543template<typename T> inline constexpr bool HasIsValid<T, std::void_t<decltype(std::declval<T>().isValid())>> = true;
     544
     545template<typename Item>
     546typename std::enable_if_t<!HasIsValid<Item>, bool> copyInto(const ItemHandle& itemHandle, uint8_t* destinationWithOffset)
     547{
     548    new (destinationWithOffset) Item(itemHandle.get<Item>());
     549    return true;
     550}
     551
     552template<typename Item>
     553typename std::enable_if_t<HasIsValid<Item>, bool> copyInto(const ItemHandle& itemHandle, uint8_t* destinationWithOffset)
     554{
     555    auto* newItem = new (destinationWithOffset) Item(itemHandle.get<Item>());
     556    return newItem->isValid();
     557}
     558
     559bool ItemHandle::safeCopy(ItemHandle destination) const
    543560{
    544561    auto itemType = type();
     
    546563    auto itemOffset = destination.data + sizeof(uint64_t);
    547564    switch (itemType) {
    548     case ItemType::ClipOutToPath: {
    549         new (itemOffset) ClipOutToPath(get<ClipOutToPath>());
    550         return;
    551     }
    552     case ItemType::ClipPath: {
    553         new (itemOffset) ClipPath(get<ClipPath>());
    554         return;
    555     }
    556     case ItemType::ClipToDrawingCommands: {
    557         new (itemOffset) ClipToDrawingCommands(get<ClipToDrawingCommands>());
    558         return;
    559     }
    560     case ItemType::DrawFocusRingPath: {
    561         new (itemOffset) DrawFocusRingPath(get<DrawFocusRingPath>());
    562         return;
    563     }
    564     case ItemType::DrawFocusRingRects: {
    565         new (itemOffset) DrawFocusRingRects(get<DrawFocusRingRects>());
    566         return;
    567     }
    568     case ItemType::DrawGlyphs: {
    569         new (itemOffset) DrawGlyphs(get<DrawGlyphs>());
    570         return;
    571     }
    572     case ItemType::DrawImageBuffer: {
    573         new (itemOffset) DrawImageBuffer(get<DrawImageBuffer>());
    574         return;
    575     }
    576     case ItemType::DrawLinesForText: {
    577         new (itemOffset) DrawLinesForText(get<DrawLinesForText>());
    578         return;
    579     }
    580     case ItemType::DrawNativeImage: {
    581         new (itemOffset) DrawNativeImage(get<DrawNativeImage>());
    582         return;
    583     }
    584     case ItemType::DrawPattern: {
    585         new (itemOffset) DrawPattern(get<DrawPattern>());
    586         return;
    587     }
    588     case ItemType::DrawPath: {
    589         new (itemOffset) DrawPath(get<DrawPath>());
    590         return;
    591     }
    592     case ItemType::FillCompositedRect: {
    593         new (itemOffset) FillCompositedRect(get<FillCompositedRect>());
    594         return;
    595     }
    596     case ItemType::FillPath: {
    597         new (itemOffset) FillPath(get<FillPath>());
    598         return;
    599     }
    600     case ItemType::FillRectWithColor: {
    601         new (itemOffset) FillRectWithColor(get<FillRectWithColor>());
    602         return;
    603     }
    604     case ItemType::FillRectWithGradient: {
    605         new (itemOffset) FillRectWithGradient(get<FillRectWithGradient>());
    606         return;
    607     }
    608     case ItemType::FillRectWithRoundedHole: {
    609         new (itemOffset) FillRectWithRoundedHole(get<FillRectWithRoundedHole>());
    610         return;
    611     }
    612     case ItemType::FillRoundedRect: {
    613         new (itemOffset) FillRoundedRect(get<FillRoundedRect>());
    614         return;
    615     }
    616     case ItemType::PutImageData: {
    617         new (itemOffset) PutImageData(get<PutImageData>());
    618         return;
    619     }
    620     case ItemType::SetLineDash: {
    621         new (itemOffset) SetLineDash(get<SetLineDash>());
    622         return;
    623     }
    624     case ItemType::SetState: {
    625         new (itemOffset) SetState(get<SetState>());
    626         return;
    627     }
    628     case ItemType::StrokePath: {
    629         new (itemOffset) StrokePath(get<StrokePath>());
    630         return;
    631     }
    632     case ItemType::ApplyDeviceScaleFactor: {
    633         new (itemOffset) ApplyDeviceScaleFactor(get<ApplyDeviceScaleFactor>());
    634         return;
    635     }
     565    case ItemType::ClipOutToPath:
     566        return copyInto<ClipOutToPath>(*this, itemOffset);
     567    case ItemType::ClipPath:
     568        return copyInto<ClipPath>(*this, itemOffset);
     569    case ItemType::ClipToDrawingCommands:
     570        return copyInto<ClipToDrawingCommands>(*this, itemOffset);
     571    case ItemType::DrawFocusRingPath:
     572        return copyInto<DrawFocusRingPath>(*this, itemOffset);
     573    case ItemType::DrawFocusRingRects:
     574        return copyInto<DrawFocusRingRects>(*this, itemOffset);
     575    case ItemType::DrawGlyphs:
     576        return copyInto<DrawGlyphs>(*this, itemOffset);
     577    case ItemType::DrawImageBuffer:
     578        return copyInto<DrawImageBuffer>(*this, itemOffset);
     579    case ItemType::DrawLinesForText:
     580        return copyInto<DrawLinesForText>(*this, itemOffset);
     581    case ItemType::DrawNativeImage:
     582        return copyInto<DrawNativeImage>(*this, itemOffset);
     583    case ItemType::DrawPattern:
     584        return copyInto<DrawPattern>(*this, itemOffset);
     585    case ItemType::DrawPath:
     586        return copyInto<DrawPath>(*this, itemOffset);
     587    case ItemType::FillCompositedRect:
     588        return copyInto<FillCompositedRect>(*this, itemOffset);
     589    case ItemType::FillPath:
     590        return copyInto<FillPath>(*this, itemOffset);
     591    case ItemType::FillRectWithColor:
     592        return copyInto<FillRectWithColor>(*this, itemOffset);
     593    case ItemType::FillRectWithGradient:
     594        return copyInto<FillRectWithGradient>(*this, itemOffset);
     595    case ItemType::FillRectWithRoundedHole:
     596        return copyInto<FillRectWithRoundedHole>(*this, itemOffset);
     597    case ItemType::FillRoundedRect:
     598        return copyInto<FillRoundedRect>(*this, itemOffset);
     599    case ItemType::PutImageData:
     600        return copyInto<PutImageData>(*this, itemOffset);
     601    case ItemType::SetLineDash:
     602        return copyInto<SetLineDash>(*this, itemOffset);
     603    case ItemType::SetState:
     604        return copyInto<SetState>(*this, itemOffset);
     605    case ItemType::StrokePath:
     606        return copyInto<StrokePath>(*this, itemOffset);
     607    case ItemType::ApplyDeviceScaleFactor:
     608        return copyInto<ApplyDeviceScaleFactor>(*this, itemOffset);
    636609#if USE(CG)
    637     case ItemType::ApplyFillPattern: {
    638         new (itemOffset) ApplyFillPattern(get<ApplyFillPattern>());
    639         return;
    640     }
    641     case ItemType::ApplyStrokePattern: {
    642         new (itemOffset) ApplyStrokePattern(get<ApplyStrokePattern>());
    643         return;
    644     }
    645 #endif
    646     case ItemType::BeginTransparencyLayer: {
    647         new (itemOffset) BeginTransparencyLayer(get<BeginTransparencyLayer>());
    648         return;
    649     }
    650     case ItemType::ClearRect: {
    651         new (itemOffset) ClearRect(get<ClearRect>());
    652         return;
    653     }
    654     case ItemType::ClearShadow: {
    655         new (itemOffset) ClearShadow(get<ClearShadow>());
    656         return;
    657     }
    658     case ItemType::Clip: {
    659         new (itemOffset) Clip(get<Clip>());
    660         return;
    661     }
    662     case ItemType::ClipOut: {
    663         new (itemOffset) ClipOut(get<ClipOut>());
    664         return;
    665     }
    666     case ItemType::ClipToImageBuffer: {
    667         new (itemOffset) ClipToImageBuffer(get<ClipToImageBuffer>());
    668         return;
    669     }
    670     case ItemType::ConcatenateCTM: {
    671         new (itemOffset) ConcatenateCTM(get<ConcatenateCTM>());
    672         return;
    673     }
    674     case ItemType::DrawDotsForDocumentMarker: {
    675         new (itemOffset) DrawDotsForDocumentMarker(get<DrawDotsForDocumentMarker>());
    676         return;
    677     }
    678     case ItemType::DrawEllipse: {
    679         new (itemOffset) DrawEllipse(get<DrawEllipse>());
    680         return;
    681     }
    682     case ItemType::DrawLine: {
    683         new (itemOffset) DrawLine(get<DrawLine>());
    684         return;
    685     }
    686     case ItemType::DrawRect: {
    687         new (itemOffset) DrawRect(get<DrawRect>());
    688         return;
    689     }
    690     case ItemType::EndTransparencyLayer: {
    691         new (itemOffset) EndTransparencyLayer(get<EndTransparencyLayer>());
    692         return;
    693     }
    694     case ItemType::FillEllipse: {
    695         new (itemOffset) FillEllipse(get<FillEllipse>());
    696         return;
    697     }
     610    case ItemType::ApplyFillPattern:
     611        return copyInto<ApplyFillPattern>(*this, itemOffset);
     612    case ItemType::ApplyStrokePattern:
     613        return copyInto<ApplyStrokePattern>(*this, itemOffset);
     614#endif
     615    case ItemType::BeginTransparencyLayer:
     616        return copyInto<BeginTransparencyLayer>(*this, itemOffset);
     617    case ItemType::ClearRect:
     618        return copyInto<ClearRect>(*this, itemOffset);
     619    case ItemType::ClearShadow:
     620        return copyInto<ClearShadow>(*this, itemOffset);
     621    case ItemType::Clip:
     622        return copyInto<Clip>(*this, itemOffset);
     623    case ItemType::ClipOut:
     624        return copyInto<ClipOut>(*this, itemOffset);
     625    case ItemType::ClipToImageBuffer:
     626        return copyInto<ClipToImageBuffer>(*this, itemOffset);
     627    case ItemType::ConcatenateCTM:
     628        return copyInto<ConcatenateCTM>(*this, itemOffset);
     629    case ItemType::DrawDotsForDocumentMarker:
     630        return copyInto<DrawDotsForDocumentMarker>(*this, itemOffset);
     631    case ItemType::DrawEllipse:
     632        return copyInto<DrawEllipse>(*this, itemOffset);
     633    case ItemType::DrawLine:
     634        return copyInto<DrawLine>(*this, itemOffset);
     635    case ItemType::DrawRect:
     636        return copyInto<DrawRect>(*this, itemOffset);
     637    case ItemType::EndTransparencyLayer:
     638        return copyInto<EndTransparencyLayer>(*this, itemOffset);
     639    case ItemType::FillEllipse:
     640        return copyInto<FillEllipse>(*this, itemOffset);
    698641#if ENABLE(INLINE_PATH_DATA)
    699     case ItemType::FillInlinePath: {
    700         new (itemOffset) FillInlinePath(get<FillInlinePath>());
    701         return;
    702     }
    703 #endif
    704     case ItemType::FillRect: {
    705         new (itemOffset) FillRect(get<FillRect>());
    706         return;
    707     }
    708     case ItemType::FlushContext: {
    709         new (itemOffset) FlushContext(get<FlushContext>());
    710         return;
    711     }
    712     case ItemType::MetaCommandChangeDestinationImageBuffer: {
    713         new (itemOffset) MetaCommandChangeDestinationImageBuffer(get<MetaCommandChangeDestinationImageBuffer>());
    714         return;
    715     }
    716     case ItemType::MetaCommandChangeItemBuffer: {
    717         new (itemOffset) MetaCommandChangeItemBuffer(get<MetaCommandChangeItemBuffer>());
    718         return;
    719     }
    720     case ItemType::PaintFrameForMedia: {
    721         new (itemOffset) PaintFrameForMedia(get<PaintFrameForMedia>());
    722         return;
    723     }
    724     case ItemType::Restore: {
    725         new (itemOffset) Restore(get<Restore>());
    726         return;
    727     }
    728     case ItemType::Rotate: {
    729         new (itemOffset) Rotate(get<Rotate>());
    730         return;
    731     }
    732     case ItemType::Save: {
    733         new (itemOffset) Save(get<Save>());
    734         return;
    735     }
    736     case ItemType::Scale: {
    737         new (itemOffset) Scale(get<Scale>());
    738         return;
    739     }
    740     case ItemType::SetCTM: {
    741         new (itemOffset) SetCTM(get<SetCTM>());
    742         return;
    743     }
    744     case ItemType::SetInlineFillColor: {
    745         new (itemOffset) SetInlineFillColor(get<SetInlineFillColor>());
    746         return;
    747     }
    748     case ItemType::SetInlineFillGradient: {
    749         new (itemOffset) SetInlineFillGradient(get<SetInlineFillGradient>());
    750         return;
    751     }
    752     case ItemType::SetInlineStrokeColor: {
    753         new (itemOffset) SetInlineStrokeColor(get<SetInlineStrokeColor>());
    754         return;
    755     }
    756     case ItemType::SetLineCap: {
    757         new (itemOffset) SetLineCap(get<SetLineCap>());
    758         return;
    759     }
    760     case ItemType::SetLineJoin: {
    761         new (itemOffset) SetLineJoin(get<SetLineJoin>());
    762         return;
    763     }
    764     case ItemType::SetMiterLimit: {
    765         new (itemOffset) SetMiterLimit(get<SetMiterLimit>());
    766         return;
    767     }
    768     case ItemType::SetStrokeThickness: {
    769         new (itemOffset) SetStrokeThickness(get<SetStrokeThickness>());
    770         return;
    771     }
    772     case ItemType::StrokeEllipse: {
    773         new (itemOffset) StrokeEllipse(get<StrokeEllipse>());
    774         return;
    775     }
     642    case ItemType::FillInlinePath:
     643        return copyInto<FillInlinePath>(*this, itemOffset);
     644#endif
     645    case ItemType::FillRect:
     646        return copyInto<FillRect>(*this, itemOffset);
     647    case ItemType::FlushContext:
     648        return copyInto<FlushContext>(*this, itemOffset);
     649    case ItemType::MetaCommandChangeDestinationImageBuffer:
     650        return copyInto<MetaCommandChangeDestinationImageBuffer>(*this, itemOffset);
     651    case ItemType::MetaCommandChangeItemBuffer:
     652        return copyInto<MetaCommandChangeItemBuffer>(*this, itemOffset);
     653    case ItemType::PaintFrameForMedia:
     654        return copyInto<PaintFrameForMedia>(*this, itemOffset);
     655    case ItemType::Restore:
     656        return copyInto<Restore>(*this, itemOffset);
     657    case ItemType::Rotate:
     658        return copyInto<Rotate>(*this, itemOffset);
     659    case ItemType::Save:
     660        return copyInto<Save>(*this, itemOffset);
     661    case ItemType::Scale:
     662        return copyInto<Scale>(*this, itemOffset);
     663    case ItemType::SetCTM:
     664        return copyInto<SetCTM>(*this, itemOffset);
     665    case ItemType::SetInlineFillColor:
     666        return copyInto<SetInlineFillColor>(*this, itemOffset);
     667    case ItemType::SetInlineFillGradient:
     668        return copyInto<SetInlineFillGradient>(*this, itemOffset);
     669    case ItemType::SetInlineStrokeColor:
     670        return copyInto<SetInlineStrokeColor>(*this, itemOffset);
     671    case ItemType::SetLineCap:
     672        return copyInto<SetLineCap>(*this, itemOffset);
     673    case ItemType::SetLineJoin:
     674        return copyInto<SetLineJoin>(*this, itemOffset);
     675    case ItemType::SetMiterLimit:
     676        return copyInto<SetMiterLimit>(*this, itemOffset);
     677    case ItemType::SetStrokeThickness:
     678        return copyInto<SetStrokeThickness>(*this, itemOffset);
     679    case ItemType::StrokeEllipse:
     680        return copyInto<StrokeEllipse>(*this, itemOffset);
    776681#if ENABLE(INLINE_PATH_DATA)
    777     case ItemType::StrokeInlinePath: {
    778         new (itemOffset) StrokeInlinePath(get<StrokeInlinePath>());
    779         return;
    780     }
    781 #endif
    782     case ItemType::StrokeRect: {
    783         new (itemOffset) StrokeRect(get<StrokeRect>());
    784         return;
    785     }
    786     case ItemType::StrokeLine: {
    787         new (itemOffset) StrokeLine(get<StrokeLine>());
    788         return;
    789     }
    790     case ItemType::Translate: {
    791         new (itemOffset) Translate(get<Translate>());
    792         return;
    793     }
    794     }
     682    case ItemType::StrokeInlinePath:
     683        return copyInto<StrokeInlinePath>(*this, itemOffset);
     684#endif
     685    case ItemType::StrokeRect:
     686        return copyInto<StrokeRect>(*this, itemOffset);
     687    case ItemType::StrokeLine:
     688        return copyInto<StrokeLine>(*this, itemOffset);
     689    case ItemType::Translate:
     690        return copyInto<Translate>(*this, itemOffset);
     691    }
     692    return false;
    795693}
    796694
  • trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemBuffer.h

    r270796 r271741  
    8181    }
    8282
    83     void copyTo(ItemHandle destination) const;
     83    bool safeCopy(ItemHandle destination) const;
    8484};
    8585
  • trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h

    r271472 r271741  
    754754    RenderingResourceIdentifier imageBufferIdentifier() const { return m_imageBufferIdentifier; }
    755755    FloatRect destinationRect() const { return m_destinationRect; }
     756    bool isValid() const { return !!m_imageBufferIdentifier; }
    756757
    757758    void apply(GraphicsContext&, WebCore::ImageBuffer&) const;
     
    10341035    FloatRect destinationRect() const { return m_destinationRect; }
    10351036    ImagePaintingOptions options() const { return m_options; }
     1037    // FIXME: We might want to validate ImagePaintingOptions.
     1038    bool isValid() const { return !!m_imageBufferIdentifier; }
    10361039
    10371040    void apply(GraphicsContext&, WebCore::ImageBuffer&) const;
     
    10671070    const FloatRect& source() const { return m_srcRect; }
    10681071    const FloatRect& destinationRect() const { return m_destinationRect; }
     1072    // FIXME: We might want to validate ImagePaintingOptions.
     1073    bool isValid() const { return !!m_imageIdentifier; }
    10691074
    10701075    NO_RETURN_DUE_TO_ASSERT void apply(GraphicsContext&) const;
     
    10971102    FloatPoint phase() const { return m_phase; }
    10981103    FloatSize spacing() const { return m_spacing; }
     1104    // FIXME: We might want to validate ImagePaintingOptions.
     1105    bool isValid() const { return !!m_imageIdentifier; }
    10991106
    11001107    NO_RETURN_DUE_TO_ASSERT void apply(GraphicsContext&) const;
     
    20002007    MediaPlayerIdentifier identifier() const { return m_identifier; }
    20012008
     2009    bool isValid() const { return !!m_identifier; }
     2010
    20022011    NO_RETURN_DUE_TO_ASSERT void apply(GraphicsContext&) const;
    20032012
     
    22242233    static constexpr bool isDrawingItem = false;
    22252234
    2226     FlushContext(FlushIdentifier identifier)
     2235    explicit FlushContext(FlushIdentifier identifier)
    22272236        : m_identifier(identifier)
    22282237    {
     
    22302239
    22312240    FlushIdentifier identifier() const { return m_identifier; }
     2241    bool isValid() const { return !!m_identifier; }
    22322242
    22332243    void apply(GraphicsContext&) const;
     
    22452255    static constexpr bool isDrawingItem = false;
    22462256
    2247     MetaCommandChangeItemBuffer(ItemBufferIdentifier identifier)
     2257    explicit MetaCommandChangeItemBuffer(ItemBufferIdentifier identifier)
    22482258        : m_identifier(identifier)
    22492259    {
     
    22512261
    22522262    ItemBufferIdentifier identifier() const { return m_identifier; }
     2263    bool isValid() const { return !!m_identifier; }
    22532264
    22542265private:
     
    22622273    static constexpr bool isDrawingItem = false;
    22632274
    2264     MetaCommandChangeDestinationImageBuffer(RenderingResourceIdentifier identifier)
     2275    explicit MetaCommandChangeDestinationImageBuffer(RenderingResourceIdentifier identifier)
    22652276        : m_identifier(identifier)
    22662277    {
     
    22682279
    22692280    RenderingResourceIdentifier identifier() const { return m_identifier; }
     2281    bool isValid() const { return !!m_identifier; }
    22702282
    22712283private:
Note: See TracChangeset for help on using the changeset viewer.