/src/mozilla-central/image/SurfacePipeFactory.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef mozilla_image_SurfacePipeFactory_h |
8 | | #define mozilla_image_SurfacePipeFactory_h |
9 | | |
10 | | #include "SurfacePipe.h" |
11 | | #include "SurfaceFilters.h" |
12 | | |
13 | | namespace mozilla { |
14 | | namespace image { |
15 | | |
16 | | namespace detail { |
17 | | |
18 | | /** |
19 | | * FilterPipeline is a helper template for SurfacePipeFactory that determines |
20 | | * the full type of the sequence of SurfaceFilters that a sequence of |
21 | | * configuration structs corresponds to. To make this work, all configuration |
22 | | * structs must include a typedef 'Filter' that identifies the SurfaceFilter |
23 | | * they configure. |
24 | | */ |
25 | | template <typename... Configs> |
26 | | struct FilterPipeline; |
27 | | |
28 | | template <typename Config, typename... Configs> |
29 | | struct FilterPipeline<Config, Configs...> |
30 | | { |
31 | | typedef typename Config::template Filter<typename FilterPipeline<Configs...>::Type> Type; |
32 | | }; |
33 | | |
34 | | template <typename Config> |
35 | | struct FilterPipeline<Config> |
36 | | { |
37 | | typedef typename Config::Filter Type; |
38 | | }; |
39 | | |
40 | | } // namespace detail |
41 | | |
42 | | /** |
43 | | * Flags for SurfacePipeFactory, used in conjuction with the factory functions |
44 | | * in SurfacePipeFactory to enable or disable various SurfacePipe |
45 | | * functionality. |
46 | | */ |
47 | | enum class SurfacePipeFlags |
48 | | { |
49 | | DEINTERLACE = 1 << 0, // If set, deinterlace the image. |
50 | | |
51 | | ADAM7_INTERPOLATE = 1 << 1, // If set, the caller is deinterlacing the |
52 | | // image using ADAM7, and we may want to |
53 | | // interpolate it for better intermediate results. |
54 | | |
55 | | FLIP_VERTICALLY = 1 << 2, // If set, flip the image vertically. |
56 | | |
57 | | PROGRESSIVE_DISPLAY = 1 << 3, // If set, we expect the image to be displayed |
58 | | // progressively. This enables features that |
59 | | // result in a better user experience for |
60 | | // progressive display but which may be more |
61 | | // computationally expensive. |
62 | | |
63 | | BLEND_ANIMATION = 1 << 4 // If set, produce the next full frame of an |
64 | | // animation instead of a partial frame to be |
65 | | // blended later. |
66 | | }; |
67 | | MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SurfacePipeFlags) |
68 | | |
69 | | class SurfacePipeFactory |
70 | | { |
71 | | public: |
72 | | /** |
73 | | * Creates and initializes a normal (i.e., non-paletted) SurfacePipe. |
74 | | * |
75 | | * @param aDecoder The decoder whose current frame the SurfacePipe will write |
76 | | * to. |
77 | | * @param aInputSize The original size of the image. |
78 | | * @param aOutputSize The size the SurfacePipe should output. Must be the same |
79 | | * as @aInputSize or smaller. If smaller, the image will be |
80 | | * downscaled during decoding. |
81 | | * @param aFrameRect The portion of the image that actually contains data. |
82 | | * @param aFormat The surface format of the image; generally B8G8R8A8 or |
83 | | * B8G8R8X8. |
84 | | * @param aAnimParams Extra parameters used by animated images. |
85 | | * @param aFlags Flags enabling or disabling various functionality for the |
86 | | * SurfacePipe; see the SurfacePipeFlags documentation for more |
87 | | * information. |
88 | | * |
89 | | * @return A SurfacePipe if the parameters allowed one to be created |
90 | | * successfully, or Nothing() if the SurfacePipe could not be |
91 | | * initialized. |
92 | | */ |
93 | | static Maybe<SurfacePipe> |
94 | | CreateSurfacePipe(Decoder* aDecoder, |
95 | | const nsIntSize& aInputSize, |
96 | | const nsIntSize& aOutputSize, |
97 | | const nsIntRect& aFrameRect, |
98 | | gfx::SurfaceFormat aFormat, |
99 | | const Maybe<AnimationParams>& aAnimParams, |
100 | | SurfacePipeFlags aFlags) |
101 | 0 | { |
102 | 0 | const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE); |
103 | 0 | const bool flipVertically = bool(aFlags & SurfacePipeFlags::FLIP_VERTICALLY); |
104 | 0 | const bool progressiveDisplay = bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY); |
105 | 0 | const bool downscale = aInputSize != aOutputSize; |
106 | 0 | const bool removeFrameRect = |
107 | 0 | !aFrameRect.IsEqualEdges(nsIntRect(0, 0, aInputSize.width, aInputSize.height)); |
108 | 0 | const bool blendAnimation = bool(aFlags & SurfacePipeFlags::BLEND_ANIMATION); |
109 | 0 |
|
110 | 0 | // Don't interpolate if we're sure we won't show this surface to the user |
111 | 0 | // until it's completely decoded. The final pass of an ADAM7 image doesn't |
112 | 0 | // need interpolation, so we only need to interpolate if we'll be displaying |
113 | 0 | // the image while it's still being decoded. |
114 | 0 | const bool adam7Interpolate = bool(aFlags & SurfacePipeFlags::ADAM7_INTERPOLATE) && |
115 | 0 | progressiveDisplay; |
116 | 0 |
|
117 | 0 | if (deinterlace && adam7Interpolate) { |
118 | 0 | MOZ_ASSERT_UNREACHABLE("ADAM7 deinterlacing is handled by libpng"); |
119 | 0 | return Nothing(); |
120 | 0 | } |
121 | 0 |
|
122 | 0 | MOZ_ASSERT_IF(blendAnimation, aAnimParams); |
123 | 0 |
|
124 | 0 | // Construct configurations for the SurfaceFilters. Note that the order of |
125 | 0 | // these filters is significant. We want to deinterlace or interpolate raw |
126 | 0 | // input rows, before any other transformations, and we want to remove the |
127 | 0 | // frame rect (which may involve adding blank rows or columns to the image) |
128 | 0 | // before any downscaling, so that the new rows and columns are taken into |
129 | 0 | // account. |
130 | 0 | DeinterlacingConfig<uint32_t> deinterlacingConfig { progressiveDisplay }; |
131 | 0 | ADAM7InterpolatingConfig interpolatingConfig; |
132 | 0 | RemoveFrameRectConfig removeFrameRectConfig { aFrameRect }; |
133 | 0 | BlendAnimationConfig blendAnimationConfig { aDecoder }; |
134 | 0 | DownscalingConfig downscalingConfig { aInputSize, aFormat }; |
135 | 0 | SurfaceConfig surfaceConfig { aDecoder, aOutputSize, aFormat, |
136 | 0 | flipVertically, aAnimParams }; |
137 | 0 |
|
138 | 0 | Maybe<SurfacePipe> pipe; |
139 | 0 |
|
140 | 0 | if (downscale) { |
141 | 0 | MOZ_ASSERT(!blendAnimation); |
142 | 0 | if (removeFrameRect) { |
143 | 0 | if (deinterlace) { |
144 | 0 | pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig, |
145 | 0 | downscalingConfig, surfaceConfig); |
146 | 0 | } else if (adam7Interpolate) { |
147 | 0 | pipe = MakePipe(interpolatingConfig, removeFrameRectConfig, |
148 | 0 | downscalingConfig, surfaceConfig); |
149 | 0 | } else { // (deinterlace and adam7Interpolate are false) |
150 | 0 | pipe = MakePipe(removeFrameRectConfig, downscalingConfig, surfaceConfig); |
151 | 0 | } |
152 | 0 | } else { // (removeFrameRect is false) |
153 | 0 | if (deinterlace) { |
154 | 0 | pipe = MakePipe(deinterlacingConfig, downscalingConfig, surfaceConfig); |
155 | 0 | } else if (adam7Interpolate) { |
156 | 0 | pipe = MakePipe(interpolatingConfig, downscalingConfig, surfaceConfig); |
157 | 0 | } else { // (deinterlace and adam7Interpolate are false) |
158 | 0 | pipe = MakePipe(downscalingConfig, surfaceConfig); |
159 | 0 | } |
160 | 0 | } |
161 | 0 | } else { // (downscale is false) |
162 | 0 | if (blendAnimation) { |
163 | 0 | if (deinterlace) { |
164 | 0 | pipe = MakePipe(deinterlacingConfig, blendAnimationConfig, surfaceConfig); |
165 | 0 | } else if (adam7Interpolate) { |
166 | 0 | pipe = MakePipe(interpolatingConfig, blendAnimationConfig, surfaceConfig); |
167 | 0 | } else { // (deinterlace and adam7Interpolate are false) |
168 | 0 | pipe = MakePipe(blendAnimationConfig, surfaceConfig); |
169 | 0 | } |
170 | 0 | } else if (removeFrameRect) { |
171 | 0 | if (deinterlace) { |
172 | 0 | pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig, surfaceConfig); |
173 | 0 | } else if (adam7Interpolate) { |
174 | 0 | pipe = MakePipe(interpolatingConfig, removeFrameRectConfig, surfaceConfig); |
175 | 0 | } else { // (deinterlace and adam7Interpolate are false) |
176 | 0 | pipe = MakePipe(removeFrameRectConfig, surfaceConfig); |
177 | 0 | } |
178 | 0 | } else { // (blendAnimation and removeFrameRect is false) |
179 | 0 | if (deinterlace) { |
180 | 0 | pipe = MakePipe(deinterlacingConfig, surfaceConfig); |
181 | 0 | } else if (adam7Interpolate) { |
182 | 0 | pipe = MakePipe(interpolatingConfig, surfaceConfig); |
183 | 0 | } else { // (deinterlace and adam7Interpolate are false) |
184 | 0 | pipe = MakePipe(surfaceConfig); |
185 | 0 | } |
186 | 0 | } |
187 | 0 | } |
188 | 0 |
|
189 | 0 | return pipe; |
190 | 0 | } |
191 | | |
192 | | /** |
193 | | * Creates and initializes a paletted SurfacePipe. |
194 | | * |
195 | | * XXX(seth): We'll remove all support for paletted surfaces in bug 1247520, |
196 | | * which means we can remove CreatePalettedSurfacePipe() entirely. |
197 | | * |
198 | | * @param aDecoder The decoder whose current frame the SurfacePipe will write |
199 | | * to. |
200 | | * @param aInputSize The original size of the image. |
201 | | * @param aFrameRect The portion of the image that actually contains data. |
202 | | * @param aFormat The surface format of the image; generally B8G8R8A8 or |
203 | | * B8G8R8X8. |
204 | | * @param aPaletteDepth The palette depth of the image. |
205 | | * @param aAnimParams Extra parameters used by animated images. |
206 | | * @param aFlags Flags enabling or disabling various functionality for the |
207 | | * SurfacePipe; see the SurfacePipeFlags documentation for more |
208 | | * information. |
209 | | * |
210 | | * @return A SurfacePipe if the parameters allowed one to be created |
211 | | * successfully, or Nothing() if the SurfacePipe could not be |
212 | | * initialized. |
213 | | */ |
214 | | static Maybe<SurfacePipe> |
215 | | CreatePalettedSurfacePipe(Decoder* aDecoder, |
216 | | const nsIntSize& aInputSize, |
217 | | const nsIntRect& aFrameRect, |
218 | | gfx::SurfaceFormat aFormat, |
219 | | uint8_t aPaletteDepth, |
220 | | const Maybe<AnimationParams>& aAnimParams, |
221 | | SurfacePipeFlags aFlags) |
222 | 0 | { |
223 | 0 | const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE); |
224 | 0 | const bool flipVertically = bool(aFlags & SurfacePipeFlags::FLIP_VERTICALLY); |
225 | 0 | const bool progressiveDisplay = bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY); |
226 | 0 |
|
227 | 0 | // Construct configurations for the SurfaceFilters. |
228 | 0 | DeinterlacingConfig<uint8_t> deinterlacingConfig { progressiveDisplay }; |
229 | 0 | PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aInputSize, aFrameRect, |
230 | 0 | aFormat, aPaletteDepth, |
231 | 0 | flipVertically, aAnimParams }; |
232 | 0 |
|
233 | 0 | Maybe<SurfacePipe> pipe; |
234 | 0 |
|
235 | 0 | if (deinterlace) { |
236 | 0 | pipe = MakePipe(deinterlacingConfig, palettedSurfaceConfig); |
237 | 0 | } else { |
238 | 0 | pipe = MakePipe(palettedSurfaceConfig); |
239 | 0 | } |
240 | 0 |
|
241 | 0 | return pipe; |
242 | 0 | } |
243 | | |
244 | | private: |
245 | | template <typename... Configs> |
246 | | static Maybe<SurfacePipe> |
247 | | MakePipe(const Configs&... aConfigs) |
248 | 0 | { |
249 | 0 | auto pipe = MakeUnique<typename detail::FilterPipeline<Configs...>::Type>(); |
250 | 0 | nsresult rv = pipe->Configure(aConfigs...); |
251 | 0 | if (NS_FAILED(rv)) { |
252 | 0 | return Nothing(); |
253 | 0 | } |
254 | 0 | |
255 | 0 | return Some(SurfacePipe { std::move(pipe) } ); |
256 | 0 | } Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::DeinterlacingConfig<unsigned int>, mozilla::image::RemoveFrameRectConfig, mozilla::image::DownscalingConfig, mozilla::image::SurfaceConfig>(mozilla::image::DeinterlacingConfig<unsigned int> const&, mozilla::image::RemoveFrameRectConfig const&, mozilla::image::DownscalingConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::ADAM7InterpolatingConfig, mozilla::image::RemoveFrameRectConfig, mozilla::image::DownscalingConfig, mozilla::image::SurfaceConfig>(mozilla::image::ADAM7InterpolatingConfig const&, mozilla::image::RemoveFrameRectConfig const&, mozilla::image::DownscalingConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::RemoveFrameRectConfig, mozilla::image::DownscalingConfig, mozilla::image::SurfaceConfig>(mozilla::image::RemoveFrameRectConfig const&, mozilla::image::DownscalingConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::DeinterlacingConfig<unsigned int>, mozilla::image::DownscalingConfig, mozilla::image::SurfaceConfig>(mozilla::image::DeinterlacingConfig<unsigned int> const&, mozilla::image::DownscalingConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::ADAM7InterpolatingConfig, mozilla::image::DownscalingConfig, mozilla::image::SurfaceConfig>(mozilla::image::ADAM7InterpolatingConfig const&, mozilla::image::DownscalingConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::DownscalingConfig, mozilla::image::SurfaceConfig>(mozilla::image::DownscalingConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::DeinterlacingConfig<unsigned int>, mozilla::image::BlendAnimationConfig, mozilla::image::SurfaceConfig>(mozilla::image::DeinterlacingConfig<unsigned int> const&, mozilla::image::BlendAnimationConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::ADAM7InterpolatingConfig, mozilla::image::BlendAnimationConfig, mozilla::image::SurfaceConfig>(mozilla::image::ADAM7InterpolatingConfig const&, mozilla::image::BlendAnimationConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::BlendAnimationConfig, mozilla::image::SurfaceConfig>(mozilla::image::BlendAnimationConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::DeinterlacingConfig<unsigned int>, mozilla::image::RemoveFrameRectConfig, mozilla::image::SurfaceConfig>(mozilla::image::DeinterlacingConfig<unsigned int> const&, mozilla::image::RemoveFrameRectConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::ADAM7InterpolatingConfig, mozilla::image::RemoveFrameRectConfig, mozilla::image::SurfaceConfig>(mozilla::image::ADAM7InterpolatingConfig const&, mozilla::image::RemoveFrameRectConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::RemoveFrameRectConfig, mozilla::image::SurfaceConfig>(mozilla::image::RemoveFrameRectConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::DeinterlacingConfig<unsigned int>, mozilla::image::SurfaceConfig>(mozilla::image::DeinterlacingConfig<unsigned int> const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::ADAM7InterpolatingConfig, mozilla::image::SurfaceConfig>(mozilla::image::ADAM7InterpolatingConfig const&, mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::SurfaceConfig>(mozilla::image::SurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::DeinterlacingConfig<unsigned char>, mozilla::image::PalettedSurfaceConfig>(mozilla::image::DeinterlacingConfig<unsigned char> const&, mozilla::image::PalettedSurfaceConfig const&) Unexecuted instantiation: mozilla::Maybe<mozilla::image::SurfacePipe> mozilla::image::SurfacePipeFactory::MakePipe<mozilla::image::PalettedSurfaceConfig>(mozilla::image::PalettedSurfaceConfig const&) |
257 | | |
258 | | virtual ~SurfacePipeFactory() = 0; |
259 | | }; |
260 | | |
261 | | } // namespace image |
262 | | } // namespace mozilla |
263 | | |
264 | | #endif // mozilla_image_SurfacePipeFactory_h |