Coverage Report

Created: 2018-09-25 14:53

/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