Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/thebes/gfxAlphaRecovery.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#ifndef _GFXALPHARECOVERY_H_
7
#define _GFXALPHARECOVERY_H_
8
9
#include "mozilla/SSE.h"
10
#include "gfxTypes.h"
11
#include "mozilla/gfx/Rect.h"
12
13
class gfxImageSurface;
14
15
class gfxAlphaRecovery {
16
public:
17
    /**
18
     * Some SIMD fast-paths only can be taken if the relative
19
     * byte-alignment of images' pointers and strides meets certain
20
     * criteria.  Aligning image pointers and strides by
21
     * |GoodAlignmentLog2()| below will ensure that fast-paths aren't
22
     * skipped because of misalignment.  Fast-paths may still be taken
23
     * even if GoodAlignmentLog2() is not met, in some conditions.
24
     */
25
    static uint32_t GoodAlignmentLog2() { return 4; /* for SSE2 */ }
26
27
    /* Given two surfaces of equal size with the same rendering, one onto a
28
     * black background and the other onto white, recovers alpha values from
29
     * the difference and sets the alpha values on the black surface.
30
     * The surfaces must have format RGB24 or ARGB32.
31
     * Returns true on success.
32
     */
33
    static bool RecoverAlpha (gfxImageSurface *blackSurface,
34
                                const gfxImageSurface *whiteSurface);
35
36
#ifdef MOZILLA_MAY_SUPPORT_SSE2
37
    /* This does the same as the previous function, but uses SSE2
38
     * optimizations. Usually this should not be called directly.  Be sure to
39
     * check mozilla::supports_sse2() before calling this function.
40
     */
41
    static bool RecoverAlphaSSE2 (gfxImageSurface *blackSurface,
42
                                    const gfxImageSurface *whiteSurface);
43
44
    /**
45
     * A common use-case for alpha recovery is to paint into a
46
     * temporary "white image", then paint onto a subrect of the
47
     * surface, the "black image", into which alpha-recovered pixels
48
     * are eventually to be written.  This function returns a rect
49
     * aligned so that recovering alpha for that rect will hit SIMD
50
     * fast-paths, if possible.  It's not always possible to align
51
     * |aRect| so that fast-paths will be taken.
52
     *
53
     * The returned rect is always a superset of |aRect|.
54
     */
55
    static mozilla::gfx::IntRect AlignRectForSubimageRecovery(const mozilla::gfx::IntRect& aRect,
56
                                                              gfxImageSurface* aSurface);
57
#else
58
    static mozilla::gfx::IntRect AlignRectForSubimageRecovery(const mozilla::gfx::IntRect& aRect,
59
                                                              gfxImageSurface*)
60
    { return aRect; }
61
#endif
62
63
    /** from cairo-xlib-utils.c, modified */
64
    /**
65
     * Given the RGB data for two image surfaces, one a source image composited
66
     * with OVER onto a black background, and one a source image composited with 
67
     * OVER onto a white background, reconstruct the original image data into
68
     * black_data.
69
     *
70
     * Consider a single color channel and a given pixel. Suppose the original
71
     * premultiplied color value was C and the alpha value was A. Let the final
72
     * on-black color be B and the final on-white color be W. All values range
73
     * over 0-255.
74
     *
75
     * Then B=C and W=(255*(255 - A) + C*255)/255. Solving for A, we get
76
     * A=255 - (W - C). Therefore it suffices to leave the black_data color
77
     * data alone and set the alpha values using that simple formula. It shouldn't
78
     * matter what color channel we pick for the alpha computation, but we'll
79
     * pick green because if we went through a color channel downsample the green
80
     * bits are likely to be the most accurate.
81
     *
82
     * This function needs to be in the header file since it's used by both
83
     * gfxRecoverAlpha.cpp and gfxRecoverAlphaSSE2.cpp.
84
     */
85
86
    static inline uint32_t
87
    RecoverPixel(uint32_t black, uint32_t white)
88
0
    {
89
0
        const uint32_t GREEN_MASK = 0x0000FF00;
90
0
        const uint32_t ALPHA_MASK = 0xFF000000;
91
0
92
0
        /* |diff| here is larger when the source image pixel is more transparent.
93
0
           If both renderings are from the same source image composited with OVER,
94
0
           then the color values on white will always be greater than those on
95
0
           black, so |diff| would not overflow.  However, overflow may happen, for
96
0
           example, when a plugin plays a video and the image is rapidly changing.
97
0
           If there is overflow, then behave as if we limit to the difference to
98
0
           >= 0, which will make the rendering opaque.  (Without this overflow
99
0
           will make the rendering transparent.) */
100
0
        uint32_t diff = (white & GREEN_MASK) - (black & GREEN_MASK);
101
0
        /* |diff| is 0xFFFFxx00 on overflow and 0x0000xx00 otherwise, so use this
102
0
            to limit the transparency. */
103
0
        uint32_t limit = diff & ALPHA_MASK;
104
0
        /* The alpha bits of the result */
105
0
        uint32_t alpha = (ALPHA_MASK - (diff << 16)) | limit;
106
0
107
0
        return alpha | (black & ~ALPHA_MASK);
108
0
    }
109
};
110
111
#endif /* _GFXALPHARECOVERY_H_ */