gfx/layers/LayerUtils.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

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.

     1 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     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/. */
     6 #include "LayerUtils.h"
     7 #include "PremultiplyTables.h"
     8 #include "mozilla/Endian.h"
    10 namespace mozilla {
    11 namespace layers {
    13 using namespace mozilla::gfx;
    15 static inline const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
    16   return PremultiplyTable[a*256+v];
    17 }
    19 static inline const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
    20   return UnpremultiplyTable[a*256+v];
    21 }
    23 #ifdef DEBUG
    24 static bool IsLittleEndian()
    25 {
    26     // Violate strict aliasing, because violating strict aliasing is how
    27     // we always pack and unpack between uint32_t and uint8_t[].
    28     uint16_t testShort;
    29     static const uint8_t testBytes[2] = { 0xAA, 0xBB };
    30     memcpy(&testShort, testBytes, sizeof(testBytes));
    31     return testShort == 0xBBAA;
    32 }
    33 #endif // DEBUG
    35 #ifdef MOZ_LITTLE_ENDIAN
    36 #define ASSERT_ENDIAN() MOZ_ASSERT(IsLittleEndian(), "Defined as little endian, but actually big!")
    37 #else
    38 #define ASSERT_ENDIAN() MOZ_ASSERT(!IsLittleEndian(), "Defined as big endian, but actually little!")
    39 #endif
    41 void
    42 PremultiplySurface(DataSourceSurface* srcSurface,
    43                    DataSourceSurface* destSurface)
    44 {
    45   if (!destSurface)
    46     destSurface = srcSurface;
    48   IntSize srcSize = srcSurface->GetSize();
    49   MOZ_ASSERT(srcSurface->GetFormat() == destSurface->GetFormat() &&
    50              srcSize.width  == destSurface->GetSize().width &&
    51              srcSize.height  == destSurface->GetSize().height &&
    52              srcSurface->Stride() == destSurface->Stride(),
    53              "Source and destination surfaces don't have identical characteristics");
    55   MOZ_ASSERT(srcSurface->Stride() == srcSize.width * 4,
    56              "Source surface stride isn't tightly packed");
    58   // Only premultiply ARGB32
    59   if (srcSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
    60     if (destSurface != srcSurface) {
    61       memcpy(destSurface->GetData(), srcSurface->GetData(),
    62              srcSurface->Stride() * srcSize.height);
    63     }
    64     return;
    65   }
    67   uint8_t *src = srcSurface->GetData();
    68   uint8_t *dst = destSurface->GetData();
    70   // Assert that our endian define is correct.
    71   ASSERT_ENDIAN();
    73   uint32_t dim = srcSize.width * srcSize.height;
    74   for (uint32_t i = 0; i < dim; ++i) {
    75 #ifdef MOZ_LITTLE_ENDIAN
    76     uint8_t b = *src++;
    77     uint8_t g = *src++;
    78     uint8_t r = *src++;
    79     uint8_t a = *src++;
    81     *dst++ = PremultiplyValue(a, b);
    82     *dst++ = PremultiplyValue(a, g);
    83     *dst++ = PremultiplyValue(a, r);
    84     *dst++ = a;
    85 #else
    86     uint8_t a = *src++;
    87     uint8_t r = *src++;
    88     uint8_t g = *src++;
    89     uint8_t b = *src++;
    91     *dst++ = a;
    92     *dst++ = PremultiplyValue(a, r);
    93     *dst++ = PremultiplyValue(a, g);
    94     *dst++ = PremultiplyValue(a, b);
    95 #endif
    96   }
    97 }
   100 }
   101 }

mercurial