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/. */
7 #ifndef mozilla_image_SurfacePipeFactory_h
8 #define mozilla_image_SurfacePipeFactory_h
10 #include "SurfacePipe.h"
11 #include "SurfaceFilters.h"
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
25 template <typename
... Configs
>
26 struct FilterPipeline
;
28 template <typename Config
, typename
... Configs
>
29 struct FilterPipeline
<Config
, Configs
...> {
30 typedef typename
Config::template Filter
<
31 typename FilterPipeline
<Configs
...>::Type
>
35 template <typename Config
>
36 struct FilterPipeline
<Config
> {
37 typedef typename
Config::Filter Type
;
43 * Flags for SurfacePipeFactory, used in conjunction with the factory functions
44 * in SurfacePipeFactory to enable or disable various SurfacePipe
47 enum class SurfacePipeFlags
{
48 DEINTERLACE
= 1 << 0, // If set, deinterlace the image.
51 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.
55 FLIP_VERTICALLY
= 1 << 2, // If set, flip the image vertically.
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.
63 PREMULTIPLY_ALPHA
= 1 << 4, // If set, we want to premultiply the alpha
64 // channel and the individual color channels.
66 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SurfacePipeFlags
)
68 class SurfacePipeFactory
{
71 * Creates and initializes a normal (i.e., non-paletted) SurfacePipe.
73 * @param aDecoder The decoder whose current frame the SurfacePipe will write
75 * @param aInputSize The original size of the image.
76 * @param aOutputSize The size the SurfacePipe should output. Must be the same
77 * as @aInputSize or smaller. If smaller, the image will be
78 * downscaled during decoding.
79 * @param aFrameRect The portion of the image that actually contains data.
80 * @param aFormat The surface format of the image; generally B8G8R8A8 or
82 * @param aAnimParams Extra parameters used by animated images.
83 * @param aFlags Flags enabling or disabling various functionality for the
84 * SurfacePipe; see the SurfacePipeFlags documentation for more
87 * @return A SurfacePipe if the parameters allowed one to be created
88 * successfully, or Nothing() if the SurfacePipe could not be
91 static Maybe
<SurfacePipe
> CreateSurfacePipe(
92 Decoder
* aDecoder
, const OrientedIntSize
& aInputSize
,
93 const OrientedIntSize
& aOutputSize
, const OrientedIntRect
& aFrameRect
,
94 gfx::SurfaceFormat aInFormat
, gfx::SurfaceFormat aOutFormat
,
95 const Maybe
<AnimationParams
>& aAnimParams
, qcms_transform
* aTransform
,
96 SurfacePipeFlags aFlags
) {
97 const bool deinterlace
= bool(aFlags
& SurfacePipeFlags::DEINTERLACE
);
98 const bool flipVertically
=
99 bool(aFlags
& SurfacePipeFlags::FLIP_VERTICALLY
);
100 const bool progressiveDisplay
=
101 bool(aFlags
& SurfacePipeFlags::PROGRESSIVE_DISPLAY
);
102 const bool downscale
= aInputSize
!= aOutputSize
;
103 const bool removeFrameRect
= !aFrameRect
.IsEqualEdges(
104 OrientedIntRect(OrientedIntPoint(0, 0), aInputSize
));
105 const bool blendAnimation
= aAnimParams
.isSome();
106 const bool colorManagement
= aTransform
!= nullptr;
107 const bool premultiplyAlpha
=
108 bool(aFlags
& SurfacePipeFlags::PREMULTIPLY_ALPHA
);
110 MOZ_ASSERT(aInFormat
== gfx::SurfaceFormat::R8G8B8
||
111 aInFormat
== gfx::SurfaceFormat::R8G8B8A8
||
112 aInFormat
== gfx::SurfaceFormat::R8G8B8X8
||
113 aInFormat
== gfx::SurfaceFormat::OS_RGBA
||
114 aInFormat
== gfx::SurfaceFormat::OS_RGBX
);
116 MOZ_ASSERT(aOutFormat
== gfx::SurfaceFormat::OS_RGBA
||
117 aOutFormat
== gfx::SurfaceFormat::OS_RGBX
);
119 MOZ_ASSERT(aDecoder
->GetOrientation().IsIdentity());
121 const bool inFormatRgb
= aInFormat
== gfx::SurfaceFormat::R8G8B8
;
123 const bool inFormatOpaque
= aInFormat
== gfx::SurfaceFormat::OS_RGBX
||
124 aInFormat
== gfx::SurfaceFormat::R8G8B8X8
||
126 const bool outFormatOpaque
= aOutFormat
== gfx::SurfaceFormat::OS_RGBX
;
128 const bool inFormatOrder
= aInFormat
== gfx::SurfaceFormat::R8G8B8A8
||
129 aInFormat
== gfx::SurfaceFormat::R8G8B8X8
;
130 const bool outFormatOrder
= aOutFormat
== gfx::SurfaceFormat::R8G8B8A8
||
131 aOutFormat
== gfx::SurfaceFormat::R8G8B8X8
;
133 // Early swizzles are for unpacking RGB or forcing RGBA/BGRA_U32 to
134 // RGBX/BGRX_U32. We should never want to premultiply in either case,
135 // because the image's alpha channel will always be opaque. This must be
136 // done before downscaling and color management.
137 bool unpackOrMaskSwizzle
=
139 (!inFormatOpaque
&& outFormatOpaque
&& inFormatOrder
== outFormatOrder
);
141 // Late swizzles are for premultiplying RGBA/BGRA_U32 and/or possible
142 // converting between RGBA and BGRA_U32. It must happen after color
143 // management, and before downscaling.
144 bool swapOrAlphaSwizzle
=
145 (!inFormatRgb
&& inFormatOrder
!= outFormatOrder
) || premultiplyAlpha
;
147 if (unpackOrMaskSwizzle
&& swapOrAlphaSwizzle
) {
148 MOZ_ASSERT_UNREACHABLE("Early and late swizzles not supported");
152 if (!unpackOrMaskSwizzle
&& !swapOrAlphaSwizzle
&&
153 aInFormat
!= aOutFormat
) {
154 MOZ_ASSERT_UNREACHABLE("Need to swizzle, but not configured to");
158 // Don't interpolate if we're sure we won't show this surface to the user
159 // until it's completely decoded. The final pass of an ADAM7 image doesn't
160 // need interpolation, so we only need to interpolate if we'll be displaying
161 // the image while it's still being decoded.
162 const bool adam7Interpolate
=
163 bool(aFlags
& SurfacePipeFlags::ADAM7_INTERPOLATE
) &&
166 if (deinterlace
&& adam7Interpolate
) {
167 MOZ_ASSERT_UNREACHABLE("ADAM7 deinterlacing is handled by libpng");
171 // Construct configurations for the SurfaceFilters. Note that the order of
172 // these filters is significant. We want to deinterlace or interpolate raw
173 // input rows, before any other transformations, and we want to remove the
174 // frame rect (which may involve adding blank rows or columns to the image)
175 // before any downscaling, so that the new rows and columns are taken into
177 DeinterlacingConfig
<uint32_t> deinterlacingConfig
{progressiveDisplay
};
178 ADAM7InterpolatingConfig interpolatingConfig
;
179 RemoveFrameRectConfig removeFrameRectConfig
{aFrameRect
.ToUnknownRect()};
180 BlendAnimationConfig blendAnimationConfig
{aDecoder
};
181 DownscalingConfig downscalingConfig
{aInputSize
.ToUnknownSize(), aOutFormat
};
182 ColorManagementConfig colorManagementConfig
{aTransform
};
183 SwizzleConfig swizzleConfig
{aInFormat
, aOutFormat
, premultiplyAlpha
};
184 SurfaceConfig surfaceConfig
{aDecoder
, aOutputSize
.ToUnknownSize(),
185 aOutFormat
, flipVertically
, aAnimParams
};
187 Maybe
<SurfacePipe
> pipe
;
189 if (unpackOrMaskSwizzle
) {
190 if (colorManagement
) {
192 MOZ_ASSERT(!blendAnimation
);
193 if (removeFrameRect
) {
195 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
196 removeFrameRectConfig
, downscalingConfig
,
197 colorManagementConfig
, surfaceConfig
);
198 } else if (adam7Interpolate
) {
199 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
200 removeFrameRectConfig
, downscalingConfig
,
201 colorManagementConfig
, surfaceConfig
);
202 } else { // (deinterlace and adam7Interpolate are false)
203 pipe
= MakePipe(swizzleConfig
, removeFrameRectConfig
,
204 downscalingConfig
, colorManagementConfig
,
207 } else { // (removeFrameRect is false)
209 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
210 downscalingConfig
, colorManagementConfig
,
212 } else if (adam7Interpolate
) {
213 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
214 downscalingConfig
, colorManagementConfig
,
216 } else { // (deinterlace and adam7Interpolate are false)
217 pipe
= MakePipe(swizzleConfig
, downscalingConfig
,
218 colorManagementConfig
, surfaceConfig
);
221 } else { // (downscale is false)
222 if (blendAnimation
) {
224 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
225 colorManagementConfig
, blendAnimationConfig
,
227 } else if (adam7Interpolate
) {
228 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
229 colorManagementConfig
, blendAnimationConfig
,
231 } else { // (deinterlace and adam7Interpolate are false)
232 pipe
= MakePipe(swizzleConfig
, colorManagementConfig
,
233 blendAnimationConfig
, surfaceConfig
);
235 } else if (removeFrameRect
) {
237 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
238 colorManagementConfig
, removeFrameRectConfig
,
240 } else if (adam7Interpolate
) {
241 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
242 colorManagementConfig
, removeFrameRectConfig
,
244 } else { // (deinterlace and adam7Interpolate are false)
245 pipe
= MakePipe(swizzleConfig
, colorManagementConfig
,
246 removeFrameRectConfig
, surfaceConfig
);
248 } else { // (blendAnimation and removeFrameRect is false)
250 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
251 colorManagementConfig
, surfaceConfig
);
252 } else if (adam7Interpolate
) {
253 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
254 colorManagementConfig
, surfaceConfig
);
255 } else { // (deinterlace and adam7Interpolate are false)
257 MakePipe(swizzleConfig
, colorManagementConfig
, surfaceConfig
);
261 } else { // (colorManagement is false)
263 MOZ_ASSERT(!blendAnimation
);
264 if (removeFrameRect
) {
266 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
267 removeFrameRectConfig
, downscalingConfig
,
269 } else if (adam7Interpolate
) {
270 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
271 removeFrameRectConfig
, downscalingConfig
,
273 } else { // (deinterlace and adam7Interpolate are false)
274 pipe
= MakePipe(swizzleConfig
, removeFrameRectConfig
,
275 downscalingConfig
, surfaceConfig
);
277 } else { // (removeFrameRect is false)
279 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
280 downscalingConfig
, surfaceConfig
);
281 } else if (adam7Interpolate
) {
282 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
283 downscalingConfig
, surfaceConfig
);
284 } else { // (deinterlace and adam7Interpolate are false)
285 pipe
= MakePipe(swizzleConfig
, downscalingConfig
, surfaceConfig
);
288 } else { // (downscale is false)
289 if (blendAnimation
) {
291 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
292 blendAnimationConfig
, surfaceConfig
);
293 } else if (adam7Interpolate
) {
294 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
295 blendAnimationConfig
, surfaceConfig
);
296 } else { // (deinterlace and adam7Interpolate are false)
298 MakePipe(swizzleConfig
, blendAnimationConfig
, surfaceConfig
);
300 } else if (removeFrameRect
) {
302 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
303 removeFrameRectConfig
, surfaceConfig
);
304 } else if (adam7Interpolate
) {
305 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
306 removeFrameRectConfig
, surfaceConfig
);
307 } else { // (deinterlace and adam7Interpolate are false)
309 MakePipe(swizzleConfig
, removeFrameRectConfig
, surfaceConfig
);
311 } else { // (blendAnimation and removeFrameRect is false)
314 MakePipe(swizzleConfig
, deinterlacingConfig
, surfaceConfig
);
315 } else if (adam7Interpolate
) {
317 MakePipe(swizzleConfig
, interpolatingConfig
, surfaceConfig
);
318 } else { // (deinterlace and adam7Interpolate are false)
319 pipe
= MakePipe(swizzleConfig
, surfaceConfig
);
324 } else if (swapOrAlphaSwizzle
) {
325 if (colorManagement
) {
327 MOZ_ASSERT(!blendAnimation
);
328 if (removeFrameRect
) {
330 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
331 deinterlacingConfig
, removeFrameRectConfig
,
332 downscalingConfig
, surfaceConfig
);
333 } else if (adam7Interpolate
) {
334 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
335 interpolatingConfig
, removeFrameRectConfig
,
336 downscalingConfig
, surfaceConfig
);
337 } else { // (deinterlace and adam7Interpolate are false)
338 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
339 removeFrameRectConfig
, downscalingConfig
,
342 } else { // (removeFrameRect is false)
344 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
345 deinterlacingConfig
, downscalingConfig
,
347 } else if (adam7Interpolate
) {
348 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
349 interpolatingConfig
, downscalingConfig
,
351 } else { // (deinterlace and adam7Interpolate are false)
352 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
353 downscalingConfig
, surfaceConfig
);
356 } else { // (downscale is false)
357 if (blendAnimation
) {
359 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
360 deinterlacingConfig
, blendAnimationConfig
,
362 } else if (adam7Interpolate
) {
363 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
364 interpolatingConfig
, blendAnimationConfig
,
366 } else { // (deinterlace and adam7Interpolate are false)
367 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
368 blendAnimationConfig
, surfaceConfig
);
370 } else if (removeFrameRect
) {
372 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
373 deinterlacingConfig
, removeFrameRectConfig
,
375 } else if (adam7Interpolate
) {
376 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
377 interpolatingConfig
, removeFrameRectConfig
,
379 } else { // (deinterlace and adam7Interpolate are false)
380 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
381 removeFrameRectConfig
, surfaceConfig
);
383 } else { // (blendAnimation and removeFrameRect is false)
385 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
386 deinterlacingConfig
, surfaceConfig
);
387 } else if (adam7Interpolate
) {
388 pipe
= MakePipe(colorManagementConfig
, swizzleConfig
,
389 interpolatingConfig
, surfaceConfig
);
390 } else { // (deinterlace and adam7Interpolate are false)
392 MakePipe(colorManagementConfig
, swizzleConfig
, surfaceConfig
);
396 } else { // (colorManagement is false)
398 MOZ_ASSERT(!blendAnimation
);
399 if (removeFrameRect
) {
401 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
402 removeFrameRectConfig
, downscalingConfig
,
404 } else if (adam7Interpolate
) {
405 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
406 removeFrameRectConfig
, downscalingConfig
,
408 } else { // (deinterlace and adam7Interpolate are false)
409 pipe
= MakePipe(swizzleConfig
, removeFrameRectConfig
,
410 downscalingConfig
, surfaceConfig
);
412 } else { // (removeFrameRect is false)
414 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
415 downscalingConfig
, surfaceConfig
);
416 } else if (adam7Interpolate
) {
417 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
418 downscalingConfig
, surfaceConfig
);
419 } else { // (deinterlace and adam7Interpolate are false)
420 pipe
= MakePipe(swizzleConfig
, downscalingConfig
, surfaceConfig
);
423 } else { // (downscale is false)
424 if (blendAnimation
) {
426 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
427 blendAnimationConfig
, surfaceConfig
);
428 } else if (adam7Interpolate
) {
429 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
430 blendAnimationConfig
, surfaceConfig
);
431 } else { // (deinterlace and adam7Interpolate are false)
433 MakePipe(swizzleConfig
, blendAnimationConfig
, surfaceConfig
);
435 } else if (removeFrameRect
) {
437 pipe
= MakePipe(swizzleConfig
, deinterlacingConfig
,
438 removeFrameRectConfig
, surfaceConfig
);
439 } else if (adam7Interpolate
) {
440 pipe
= MakePipe(swizzleConfig
, interpolatingConfig
,
441 removeFrameRectConfig
, surfaceConfig
);
442 } else { // (deinterlace and adam7Interpolate are false)
444 MakePipe(swizzleConfig
, removeFrameRectConfig
, surfaceConfig
);
446 } else { // (blendAnimation and removeFrameRect is false)
449 MakePipe(swizzleConfig
, deinterlacingConfig
, surfaceConfig
);
450 } else if (adam7Interpolate
) {
452 MakePipe(swizzleConfig
, interpolatingConfig
, surfaceConfig
);
453 } else { // (deinterlace and adam7Interpolate are false)
454 pipe
= MakePipe(swizzleConfig
, surfaceConfig
);
459 } else { // (unpackOrMaskSwizzle and swapOrAlphaSwizzle are false)
460 if (colorManagement
) {
462 MOZ_ASSERT(!blendAnimation
);
463 if (removeFrameRect
) {
465 pipe
= MakePipe(deinterlacingConfig
, removeFrameRectConfig
,
466 downscalingConfig
, colorManagementConfig
,
468 } else if (adam7Interpolate
) {
469 pipe
= MakePipe(interpolatingConfig
, removeFrameRectConfig
,
470 downscalingConfig
, colorManagementConfig
,
472 } else { // (deinterlace and adam7Interpolate are false)
473 pipe
= MakePipe(removeFrameRectConfig
, downscalingConfig
,
474 colorManagementConfig
, surfaceConfig
);
476 } else { // (removeFrameRect is false)
478 pipe
= MakePipe(deinterlacingConfig
, downscalingConfig
,
479 colorManagementConfig
, surfaceConfig
);
480 } else if (adam7Interpolate
) {
481 pipe
= MakePipe(interpolatingConfig
, downscalingConfig
,
482 colorManagementConfig
, surfaceConfig
);
483 } else { // (deinterlace and adam7Interpolate are false)
484 pipe
= MakePipe(downscalingConfig
, colorManagementConfig
,
488 } else { // (downscale is false)
489 if (blendAnimation
) {
491 pipe
= MakePipe(deinterlacingConfig
, colorManagementConfig
,
492 blendAnimationConfig
, surfaceConfig
);
493 } else if (adam7Interpolate
) {
494 pipe
= MakePipe(interpolatingConfig
, colorManagementConfig
,
495 blendAnimationConfig
, surfaceConfig
);
496 } else { // (deinterlace and adam7Interpolate are false)
497 pipe
= MakePipe(colorManagementConfig
, blendAnimationConfig
,
500 } else if (removeFrameRect
) {
502 pipe
= MakePipe(deinterlacingConfig
, colorManagementConfig
,
503 removeFrameRectConfig
, surfaceConfig
);
504 } else if (adam7Interpolate
) {
505 pipe
= MakePipe(interpolatingConfig
, colorManagementConfig
,
506 removeFrameRectConfig
, surfaceConfig
);
507 } else { // (deinterlace and adam7Interpolate are false)
508 pipe
= MakePipe(colorManagementConfig
, removeFrameRectConfig
,
511 } else { // (blendAnimation and removeFrameRect is false)
513 pipe
= MakePipe(deinterlacingConfig
, colorManagementConfig
,
515 } else if (adam7Interpolate
) {
516 pipe
= MakePipe(interpolatingConfig
, colorManagementConfig
,
518 } else { // (deinterlace and adam7Interpolate are false)
519 pipe
= MakePipe(colorManagementConfig
, surfaceConfig
);
523 } else { // (colorManagement is false)
525 MOZ_ASSERT(!blendAnimation
);
526 if (removeFrameRect
) {
528 pipe
= MakePipe(deinterlacingConfig
, removeFrameRectConfig
,
529 downscalingConfig
, surfaceConfig
);
530 } else if (adam7Interpolate
) {
531 pipe
= MakePipe(interpolatingConfig
, removeFrameRectConfig
,
532 downscalingConfig
, surfaceConfig
);
533 } else { // (deinterlace and adam7Interpolate are false)
534 pipe
= MakePipe(removeFrameRectConfig
, downscalingConfig
,
537 } else { // (removeFrameRect is false)
539 pipe
= MakePipe(deinterlacingConfig
, downscalingConfig
,
541 } else if (adam7Interpolate
) {
542 pipe
= MakePipe(interpolatingConfig
, downscalingConfig
,
544 } else { // (deinterlace and adam7Interpolate are false)
545 pipe
= MakePipe(downscalingConfig
, surfaceConfig
);
548 } else { // (downscale is false)
549 if (blendAnimation
) {
551 pipe
= MakePipe(deinterlacingConfig
, blendAnimationConfig
,
553 } else if (adam7Interpolate
) {
554 pipe
= MakePipe(interpolatingConfig
, blendAnimationConfig
,
556 } else { // (deinterlace and adam7Interpolate are false)
557 pipe
= MakePipe(blendAnimationConfig
, surfaceConfig
);
559 } else if (removeFrameRect
) {
561 pipe
= MakePipe(deinterlacingConfig
, removeFrameRectConfig
,
563 } else if (adam7Interpolate
) {
564 pipe
= MakePipe(interpolatingConfig
, removeFrameRectConfig
,
566 } else { // (deinterlace and adam7Interpolate are false)
567 pipe
= MakePipe(removeFrameRectConfig
, surfaceConfig
);
569 } else { // (blendAnimation and removeFrameRect is false)
571 pipe
= MakePipe(deinterlacingConfig
, surfaceConfig
);
572 } else if (adam7Interpolate
) {
573 pipe
= MakePipe(interpolatingConfig
, surfaceConfig
);
574 } else { // (deinterlace and adam7Interpolate are false)
575 pipe
= MakePipe(surfaceConfig
);
586 * Creates and initializes a reorienting SurfacePipe.
588 * @param aDecoder The decoder whose current frame the SurfacePipe will write
590 * @param aInputSize The original size of the image.
591 * @param aOutputSize The size the SurfacePipe should output. Must be the same
592 * as @aInputSize or smaller. If smaller, the image will be
593 * downscaled during decoding.
594 * @param aFormat The surface format of the image; generally B8G8R8A8 or
596 * @param aOrientation The orientation of the image.
598 * @return A SurfacePipe if the parameters allowed one to be created
599 * successfully, or Nothing() if the SurfacePipe could not be
602 static Maybe
<SurfacePipe
> CreateReorientSurfacePipe(
603 Decoder
* aDecoder
, const OrientedIntSize
& aInputSize
,
604 const OrientedIntSize
& aOutputSize
, gfx::SurfaceFormat aFormat
,
605 qcms_transform
* aTransform
, const Orientation
& aOrientation
) {
606 const bool downscale
= aInputSize
!= aOutputSize
;
607 const bool colorManagement
= aTransform
!= nullptr;
609 // Construct configurations for the SurfaceFilters. Note that the order of
610 // these filters is significant. We want to deinterlace or interpolate raw
611 // input rows, before any other transformations, and we want to remove the
612 // frame rect (which may involve adding blank rows or columns to the image)
613 // before any downscaling, so that the new rows and columns are taken into
615 DownscalingConfig downscalingConfig
{
616 aOrientation
.ToUnoriented(aInputSize
).ToUnknownSize(), aFormat
};
617 ColorManagementConfig colorManagementConfig
{aTransform
};
618 SurfaceConfig surfaceConfig
{aDecoder
, aOutputSize
.ToUnknownSize(), aFormat
,
619 /* mFlipVertically */ false,
620 /* mAnimParams */ Nothing()};
621 ReorientSurfaceConfig reorientSurfaceConfig
{aDecoder
, aOutputSize
, aFormat
,
624 Maybe
<SurfacePipe
> pipe
;
626 if (aOrientation
.IsIdentity()) {
627 if (colorManagement
) {
630 MakePipe(downscalingConfig
, colorManagementConfig
, surfaceConfig
);
631 } else { // (downscale is false)
632 pipe
= MakePipe(colorManagementConfig
, surfaceConfig
);
634 } else { // (colorManagement is false)
636 pipe
= MakePipe(downscalingConfig
, surfaceConfig
);
637 } else { // (downscale is false)
638 pipe
= MakePipe(surfaceConfig
);
641 } else { // (orientation is not identity)
642 if (colorManagement
) {
644 pipe
= MakePipe(downscalingConfig
, colorManagementConfig
,
645 reorientSurfaceConfig
);
646 } else { // (downscale is false)
647 pipe
= MakePipe(colorManagementConfig
, reorientSurfaceConfig
);
649 } else { // (colorManagement is false)
651 pipe
= MakePipe(downscalingConfig
, reorientSurfaceConfig
);
652 } else { // (downscale is false)
653 pipe
= MakePipe(reorientSurfaceConfig
);
662 template <typename
... Configs
>
663 static Maybe
<SurfacePipe
> MakePipe(const Configs
&... aConfigs
) {
664 auto pipe
= MakeUnique
<typename
detail::FilterPipeline
<Configs
...>::Type
>();
665 nsresult rv
= pipe
->Configure(aConfigs
...);
670 return Some(SurfacePipe
{std::move(pipe
)});
673 virtual ~SurfacePipeFactory() = 0;
677 } // namespace mozilla
679 #endif // mozilla_image_SurfacePipeFactory_h