Backed out changeset f020820671c4 (bug 1833403) for causing reftest failures on resiz...
[gecko.git] / image / SurfacePipeFactory.h
blob004ce349a68c049976f5c4797a59d33a57782398
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"
13 namespace mozilla {
14 namespace image {
16 namespace detail {
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.
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>
32 Type;
35 template <typename Config>
36 struct FilterPipeline<Config> {
37 typedef typename Config::Filter Type;
40 } // namespace detail
42 /**
43 * Flags for SurfacePipeFactory, used in conjunction with the factory functions
44 * in SurfacePipeFactory to enable or disable various SurfacePipe
45 * functionality.
47 enum class SurfacePipeFlags {
48 DEINTERLACE = 1 << 0, // If set, deinterlace the image.
50 ADAM7_INTERPOLATE =
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 {
69 public:
70 /**
71 * Creates and initializes a normal (i.e., non-paletted) SurfacePipe.
73 * @param aDecoder The decoder whose current frame the SurfacePipe will write
74 * to.
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
81 * B8G8R8X8.
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
85 * information.
87 * @return A SurfacePipe if the parameters allowed one to be created
88 * successfully, or Nothing() if the SurfacePipe could not be
89 * initialized.
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 ||
125 inFormatRgb;
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 =
138 inFormatRgb ||
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");
149 return Nothing();
152 if (!unpackOrMaskSwizzle && !swapOrAlphaSwizzle &&
153 aInFormat != aOutFormat) {
154 MOZ_ASSERT_UNREACHABLE("Need to swizzle, but not configured to");
155 return Nothing();
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) &&
164 progressiveDisplay;
166 if (deinterlace && adam7Interpolate) {
167 MOZ_ASSERT_UNREACHABLE("ADAM7 deinterlacing is handled by libpng");
168 return Nothing();
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
176 // account.
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) {
191 if (downscale) {
192 MOZ_ASSERT(!blendAnimation);
193 if (removeFrameRect) {
194 if (deinterlace) {
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,
205 surfaceConfig);
207 } else { // (removeFrameRect is false)
208 if (deinterlace) {
209 pipe = MakePipe(swizzleConfig, deinterlacingConfig,
210 downscalingConfig, colorManagementConfig,
211 surfaceConfig);
212 } else if (adam7Interpolate) {
213 pipe = MakePipe(swizzleConfig, interpolatingConfig,
214 downscalingConfig, colorManagementConfig,
215 surfaceConfig);
216 } else { // (deinterlace and adam7Interpolate are false)
217 pipe = MakePipe(swizzleConfig, downscalingConfig,
218 colorManagementConfig, surfaceConfig);
221 } else { // (downscale is false)
222 if (blendAnimation) {
223 if (deinterlace) {
224 pipe = MakePipe(swizzleConfig, deinterlacingConfig,
225 colorManagementConfig, blendAnimationConfig,
226 surfaceConfig);
227 } else if (adam7Interpolate) {
228 pipe = MakePipe(swizzleConfig, interpolatingConfig,
229 colorManagementConfig, blendAnimationConfig,
230 surfaceConfig);
231 } else { // (deinterlace and adam7Interpolate are false)
232 pipe = MakePipe(swizzleConfig, colorManagementConfig,
233 blendAnimationConfig, surfaceConfig);
235 } else if (removeFrameRect) {
236 if (deinterlace) {
237 pipe = MakePipe(swizzleConfig, deinterlacingConfig,
238 colorManagementConfig, removeFrameRectConfig,
239 surfaceConfig);
240 } else if (adam7Interpolate) {
241 pipe = MakePipe(swizzleConfig, interpolatingConfig,
242 colorManagementConfig, removeFrameRectConfig,
243 surfaceConfig);
244 } else { // (deinterlace and adam7Interpolate are false)
245 pipe = MakePipe(swizzleConfig, colorManagementConfig,
246 removeFrameRectConfig, surfaceConfig);
248 } else { // (blendAnimation and removeFrameRect is false)
249 if (deinterlace) {
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)
256 pipe =
257 MakePipe(swizzleConfig, colorManagementConfig, surfaceConfig);
261 } else { // (colorManagement is false)
262 if (downscale) {
263 MOZ_ASSERT(!blendAnimation);
264 if (removeFrameRect) {
265 if (deinterlace) {
266 pipe = MakePipe(swizzleConfig, deinterlacingConfig,
267 removeFrameRectConfig, downscalingConfig,
268 surfaceConfig);
269 } else if (adam7Interpolate) {
270 pipe = MakePipe(swizzleConfig, interpolatingConfig,
271 removeFrameRectConfig, downscalingConfig,
272 surfaceConfig);
273 } else { // (deinterlace and adam7Interpolate are false)
274 pipe = MakePipe(swizzleConfig, removeFrameRectConfig,
275 downscalingConfig, surfaceConfig);
277 } else { // (removeFrameRect is false)
278 if (deinterlace) {
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) {
290 if (deinterlace) {
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)
297 pipe =
298 MakePipe(swizzleConfig, blendAnimationConfig, surfaceConfig);
300 } else if (removeFrameRect) {
301 if (deinterlace) {
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)
308 pipe =
309 MakePipe(swizzleConfig, removeFrameRectConfig, surfaceConfig);
311 } else { // (blendAnimation and removeFrameRect is false)
312 if (deinterlace) {
313 pipe =
314 MakePipe(swizzleConfig, deinterlacingConfig, surfaceConfig);
315 } else if (adam7Interpolate) {
316 pipe =
317 MakePipe(swizzleConfig, interpolatingConfig, surfaceConfig);
318 } else { // (deinterlace and adam7Interpolate are false)
319 pipe = MakePipe(swizzleConfig, surfaceConfig);
324 } else if (swapOrAlphaSwizzle) {
325 if (colorManagement) {
326 if (downscale) {
327 MOZ_ASSERT(!blendAnimation);
328 if (removeFrameRect) {
329 if (deinterlace) {
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,
340 surfaceConfig);
342 } else { // (removeFrameRect is false)
343 if (deinterlace) {
344 pipe = MakePipe(colorManagementConfig, swizzleConfig,
345 deinterlacingConfig, downscalingConfig,
346 surfaceConfig);
347 } else if (adam7Interpolate) {
348 pipe = MakePipe(colorManagementConfig, swizzleConfig,
349 interpolatingConfig, downscalingConfig,
350 surfaceConfig);
351 } else { // (deinterlace and adam7Interpolate are false)
352 pipe = MakePipe(colorManagementConfig, swizzleConfig,
353 downscalingConfig, surfaceConfig);
356 } else { // (downscale is false)
357 if (blendAnimation) {
358 if (deinterlace) {
359 pipe = MakePipe(colorManagementConfig, swizzleConfig,
360 deinterlacingConfig, blendAnimationConfig,
361 surfaceConfig);
362 } else if (adam7Interpolate) {
363 pipe = MakePipe(colorManagementConfig, swizzleConfig,
364 interpolatingConfig, blendAnimationConfig,
365 surfaceConfig);
366 } else { // (deinterlace and adam7Interpolate are false)
367 pipe = MakePipe(colorManagementConfig, swizzleConfig,
368 blendAnimationConfig, surfaceConfig);
370 } else if (removeFrameRect) {
371 if (deinterlace) {
372 pipe = MakePipe(colorManagementConfig, swizzleConfig,
373 deinterlacingConfig, removeFrameRectConfig,
374 surfaceConfig);
375 } else if (adam7Interpolate) {
376 pipe = MakePipe(colorManagementConfig, swizzleConfig,
377 interpolatingConfig, removeFrameRectConfig,
378 surfaceConfig);
379 } else { // (deinterlace and adam7Interpolate are false)
380 pipe = MakePipe(colorManagementConfig, swizzleConfig,
381 removeFrameRectConfig, surfaceConfig);
383 } else { // (blendAnimation and removeFrameRect is false)
384 if (deinterlace) {
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)
391 pipe =
392 MakePipe(colorManagementConfig, swizzleConfig, surfaceConfig);
396 } else { // (colorManagement is false)
397 if (downscale) {
398 MOZ_ASSERT(!blendAnimation);
399 if (removeFrameRect) {
400 if (deinterlace) {
401 pipe = MakePipe(swizzleConfig, deinterlacingConfig,
402 removeFrameRectConfig, downscalingConfig,
403 surfaceConfig);
404 } else if (adam7Interpolate) {
405 pipe = MakePipe(swizzleConfig, interpolatingConfig,
406 removeFrameRectConfig, downscalingConfig,
407 surfaceConfig);
408 } else { // (deinterlace and adam7Interpolate are false)
409 pipe = MakePipe(swizzleConfig, removeFrameRectConfig,
410 downscalingConfig, surfaceConfig);
412 } else { // (removeFrameRect is false)
413 if (deinterlace) {
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) {
425 if (deinterlace) {
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)
432 pipe =
433 MakePipe(swizzleConfig, blendAnimationConfig, surfaceConfig);
435 } else if (removeFrameRect) {
436 if (deinterlace) {
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)
443 pipe =
444 MakePipe(swizzleConfig, removeFrameRectConfig, surfaceConfig);
446 } else { // (blendAnimation and removeFrameRect is false)
447 if (deinterlace) {
448 pipe =
449 MakePipe(swizzleConfig, deinterlacingConfig, surfaceConfig);
450 } else if (adam7Interpolate) {
451 pipe =
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) {
461 if (downscale) {
462 MOZ_ASSERT(!blendAnimation);
463 if (removeFrameRect) {
464 if (deinterlace) {
465 pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig,
466 downscalingConfig, colorManagementConfig,
467 surfaceConfig);
468 } else if (adam7Interpolate) {
469 pipe = MakePipe(interpolatingConfig, removeFrameRectConfig,
470 downscalingConfig, colorManagementConfig,
471 surfaceConfig);
472 } else { // (deinterlace and adam7Interpolate are false)
473 pipe = MakePipe(removeFrameRectConfig, downscalingConfig,
474 colorManagementConfig, surfaceConfig);
476 } else { // (removeFrameRect is false)
477 if (deinterlace) {
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,
485 surfaceConfig);
488 } else { // (downscale is false)
489 if (blendAnimation) {
490 if (deinterlace) {
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,
498 surfaceConfig);
500 } else if (removeFrameRect) {
501 if (deinterlace) {
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,
509 surfaceConfig);
511 } else { // (blendAnimation and removeFrameRect is false)
512 if (deinterlace) {
513 pipe = MakePipe(deinterlacingConfig, colorManagementConfig,
514 surfaceConfig);
515 } else if (adam7Interpolate) {
516 pipe = MakePipe(interpolatingConfig, colorManagementConfig,
517 surfaceConfig);
518 } else { // (deinterlace and adam7Interpolate are false)
519 pipe = MakePipe(colorManagementConfig, surfaceConfig);
523 } else { // (colorManagement is false)
524 if (downscale) {
525 MOZ_ASSERT(!blendAnimation);
526 if (removeFrameRect) {
527 if (deinterlace) {
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,
535 surfaceConfig);
537 } else { // (removeFrameRect is false)
538 if (deinterlace) {
539 pipe = MakePipe(deinterlacingConfig, downscalingConfig,
540 surfaceConfig);
541 } else if (adam7Interpolate) {
542 pipe = MakePipe(interpolatingConfig, downscalingConfig,
543 surfaceConfig);
544 } else { // (deinterlace and adam7Interpolate are false)
545 pipe = MakePipe(downscalingConfig, surfaceConfig);
548 } else { // (downscale is false)
549 if (blendAnimation) {
550 if (deinterlace) {
551 pipe = MakePipe(deinterlacingConfig, blendAnimationConfig,
552 surfaceConfig);
553 } else if (adam7Interpolate) {
554 pipe = MakePipe(interpolatingConfig, blendAnimationConfig,
555 surfaceConfig);
556 } else { // (deinterlace and adam7Interpolate are false)
557 pipe = MakePipe(blendAnimationConfig, surfaceConfig);
559 } else if (removeFrameRect) {
560 if (deinterlace) {
561 pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig,
562 surfaceConfig);
563 } else if (adam7Interpolate) {
564 pipe = MakePipe(interpolatingConfig, removeFrameRectConfig,
565 surfaceConfig);
566 } else { // (deinterlace and adam7Interpolate are false)
567 pipe = MakePipe(removeFrameRectConfig, surfaceConfig);
569 } else { // (blendAnimation and removeFrameRect is false)
570 if (deinterlace) {
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);
582 return pipe;
586 * Creates and initializes a reorienting SurfacePipe.
588 * @param aDecoder The decoder whose current frame the SurfacePipe will write
589 * to.
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
595 * B8G8R8X8.
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
600 * initialized.
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
614 // account.
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,
622 aOrientation};
624 Maybe<SurfacePipe> pipe;
626 if (aOrientation.IsIdentity()) {
627 if (colorManagement) {
628 if (downscale) {
629 pipe =
630 MakePipe(downscalingConfig, colorManagementConfig, surfaceConfig);
631 } else { // (downscale is false)
632 pipe = MakePipe(colorManagementConfig, surfaceConfig);
634 } else { // (colorManagement is false)
635 if (downscale) {
636 pipe = MakePipe(downscalingConfig, surfaceConfig);
637 } else { // (downscale is false)
638 pipe = MakePipe(surfaceConfig);
641 } else { // (orientation is not identity)
642 if (colorManagement) {
643 if (downscale) {
644 pipe = MakePipe(downscalingConfig, colorManagementConfig,
645 reorientSurfaceConfig);
646 } else { // (downscale is false)
647 pipe = MakePipe(colorManagementConfig, reorientSurfaceConfig);
649 } else { // (colorManagement is false)
650 if (downscale) {
651 pipe = MakePipe(downscalingConfig, reorientSurfaceConfig);
652 } else { // (downscale is false)
653 pipe = MakePipe(reorientSurfaceConfig);
658 return pipe;
661 private:
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...);
666 if (NS_FAILED(rv)) {
667 return Nothing();
670 return Some(SurfacePipe{std::move(pipe)});
673 virtual ~SurfacePipeFactory() = 0;
676 } // namespace image
677 } // namespace mozilla
679 #endif // mozilla_image_SurfacePipeFactory_h