Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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_ */ |