REGRESSION (216471): Infinite repaint-drawing loop when asynchronously decoding incom...
[WebKit-https.git] / Source / WebCore / platform / graphics / ImageFrameCache.h
1 /*
2  * Copyright (C) 2016 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "ImageFrame.h"
29 #include "TextStream.h"
30
31 #include <wtf/Forward.h>
32 #include <wtf/Optional.h>
33 #include <wtf/SynchronizedFixedQueue.h>
34 #include <wtf/WorkQueue.h>
35 #include <wtf/threads/BinarySemaphore.h>
36
37 namespace WebCore {
38
39 class GraphicsContext;
40 class Image;
41 class ImageDecoder;
42 class URL;
43
44 class ImageFrameCache : public RefCounted<ImageFrameCache> {
45     friend class ImageSource;
46 public:
47     static Ref<ImageFrameCache> create(Image* image)
48     {
49         return adoptRef(*new ImageFrameCache(image));
50     }
51
52     static Ref<ImageFrameCache> create(NativeImagePtr&& nativeImage)
53     {
54         return adoptRef(*new ImageFrameCache(WTFMove(nativeImage)));
55     }
56
57     ~ImageFrameCache();
58
59     void setDecoder(ImageDecoder*);
60     ImageDecoder* decoder() const;
61
62     unsigned decodedSize() const { return m_decodedSize; }
63     void destroyAllDecodedData() { destroyDecodedData(frameCount(), frameCount()); }
64     void destroyAllDecodedDataExcludeFrame(size_t excludeFrame) { destroyDecodedData(frameCount(), excludeFrame); }
65     void destroyDecodedDataBeforeFrame(size_t beforeFrame) { destroyDecodedData(beforeFrame, beforeFrame); }
66     void destroyIncompleteDecodedData();
67
68     void growFrames();
69     void clearMetadata();
70     URL sourceURL() const;
71     
72     // Asynchronous image decoding
73     void startAsyncDecodingQueue();
74     void requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel, const std::optional<IntSize>&);
75     void stopAsyncDecodingQueue();
76     bool hasAsyncDecodingQueue() const { return m_decodingQueue; }
77     bool isAsyncDecodingQueueIdle() const;
78
79     // Image metadata which is calculated either by the ImageDecoder or directly
80     // from the NativeImage if this class was created for a memory image.
81     EncodedDataStatus encodedDataStatus();
82     bool isSizeAvailable() { return encodedDataStatus() >= EncodedDataStatus::SizeAvailable; }
83     size_t frameCount();
84     RepetitionCount repetitionCount();
85     String uti();
86     String filenameExtension();
87     std::optional<IntPoint> hotSpot();
88     
89     // Image metadata which is calculated from the first ImageFrame.
90     IntSize size();
91     IntSize sizeRespectingOrientation();
92
93     Color singlePixelSolidColor();
94
95     // ImageFrame metadata which does not require caching the ImageFrame.
96     bool frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(size_t, const DecodingOptions&);
97     ImageFrame::DecodingStatus frameDecodingStatusAtIndex(size_t);
98     bool frameHasAlphaAtIndex(size_t);
99     bool frameHasImageAtIndex(size_t);
100     bool frameHasFullSizeNativeImageAtIndex(size_t, const std::optional<SubsamplingLevel>&);
101     bool frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(size_t, const std::optional<SubsamplingLevel>&, const DecodingOptions&);
102     SubsamplingLevel frameSubsamplingLevelAtIndex(size_t);
103
104     // ImageFrame metadata which forces caching or re-caching the ImageFrame.
105     IntSize frameSizeAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
106     unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
107     float frameDurationAtIndex(size_t);
108     ImageOrientation frameOrientationAtIndex(size_t);
109
110     NativeImagePtr frameImageAtIndex(size_t);
111     NativeImagePtr frameImageAtIndexCacheIfNeeded(size_t, SubsamplingLevel);
112
113 private:
114     ImageFrameCache(Image*);
115     ImageFrameCache(NativeImagePtr&&);
116
117     template<typename T, T (ImageDecoder::*functor)() const>
118     T metadata(const T& defaultValue, std::optional<T>* cachedValue = nullptr);
119
120     template<typename T, typename... Args>
121     T frameMetadataAtIndex(size_t, T (ImageFrame::*functor)(Args...) const, Args&&...);
122
123     template<typename T, typename... Args>
124     T frameMetadataAtIndexCacheIfNeeded(size_t, T (ImageFrame::*functor)() const,  std::optional<T>* cachedValue, Args&&...);
125
126     bool isDecoderAvailable() const { return m_decoder; }
127     void destroyDecodedData(size_t frameCount, size_t excludeFrame);
128     void decodedSizeChanged(long long decodedSize);
129     void didDecodeProperties(unsigned decodedPropertiesSize);
130     void decodedSizeIncreased(unsigned decodedSize);
131     void decodedSizeDecreased(unsigned decodedSize);
132     void decodedSizeReset(unsigned decodedSize);
133
134     void setNativeImage(NativeImagePtr&&);
135     void cacheMetadataAtIndex(size_t, SubsamplingLevel, ImageFrame::DecodingStatus = ImageFrame::DecodingStatus::Invalid);
136     void cacheNativeImageAtIndex(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, ImageFrame::DecodingStatus = ImageFrame::DecodingStatus::Invalid);
137     void cacheNativeImageAtIndexAsync(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, ImageFrame::DecodingStatus);
138
139     Ref<WorkQueue> decodingQueue();
140
141     const ImageFrame& frameAtIndexCacheIfNeeded(size_t, ImageFrame::Caching, const std::optional<SubsamplingLevel>& = { });
142
143     Image* m_image { nullptr };
144     RefPtr<ImageDecoder> m_decoder;
145     unsigned m_decodedSize { 0 };
146     unsigned m_decodedPropertiesSize { 0 };
147
148     Vector<ImageFrame, 1> m_frames;
149
150     // Asynchronous image decoding.
151     struct ImageFrameRequest {
152         size_t index;
153         SubsamplingLevel subsamplingLevel;
154         DecodingOptions decodingOptions;
155         ImageFrame::DecodingStatus decodingStatus;
156         bool operator==(const ImageFrameRequest& other) const
157         {
158             return index == other.index && subsamplingLevel == other.subsamplingLevel && decodingOptions == other.decodingOptions && decodingStatus == other.decodingStatus;
159         }
160     };
161     static const int BufferSize = 8;
162     using FrameRequestQueue = SynchronizedFixedQueue<ImageFrameRequest, BufferSize>;
163     using FrameCommitQueue = Deque<ImageFrameRequest, BufferSize>;
164     FrameRequestQueue m_frameRequestQueue;
165     FrameCommitQueue m_frameCommitQueue;
166     RefPtr<WorkQueue> m_decodingQueue;
167
168     // Image metadata.
169     std::optional<EncodedDataStatus> m_encodedDataStatus;
170     std::optional<size_t> m_frameCount;
171     std::optional<RepetitionCount> m_repetitionCount;
172     std::optional<String> m_uti;
173     std::optional<String> m_filenameExtension;
174     std::optional<std::optional<IntPoint>> m_hotSpot;
175
176     // Image metadata which is calculated from the first ImageFrame.
177     std::optional<IntSize> m_size;
178     std::optional<IntSize> m_sizeRespectingOrientation;
179     std::optional<Color> m_singlePixelSolidColor;
180 };
181     
182 }