gfx/thebes/gfxAlphaRecovery.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial