gfx/layers/LayerUtils.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/LayerUtils.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,101 @@
     1.4 +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "LayerUtils.h"
    1.10 +#include "PremultiplyTables.h"
    1.11 +#include "mozilla/Endian.h"
    1.12 +
    1.13 +namespace mozilla {
    1.14 +namespace layers {
    1.15 +
    1.16 +using namespace mozilla::gfx;
    1.17 +
    1.18 +static inline const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
    1.19 +  return PremultiplyTable[a*256+v];
    1.20 +}
    1.21 +
    1.22 +static inline const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
    1.23 +  return UnpremultiplyTable[a*256+v];
    1.24 +}
    1.25 +
    1.26 +#ifdef DEBUG
    1.27 +static bool IsLittleEndian()
    1.28 +{
    1.29 +    // Violate strict aliasing, because violating strict aliasing is how
    1.30 +    // we always pack and unpack between uint32_t and uint8_t[].
    1.31 +    uint16_t testShort;
    1.32 +    static const uint8_t testBytes[2] = { 0xAA, 0xBB };
    1.33 +    memcpy(&testShort, testBytes, sizeof(testBytes));
    1.34 +    return testShort == 0xBBAA;
    1.35 +}
    1.36 +#endif // DEBUG
    1.37 +
    1.38 +#ifdef MOZ_LITTLE_ENDIAN
    1.39 +#define ASSERT_ENDIAN() MOZ_ASSERT(IsLittleEndian(), "Defined as little endian, but actually big!")
    1.40 +#else
    1.41 +#define ASSERT_ENDIAN() MOZ_ASSERT(!IsLittleEndian(), "Defined as big endian, but actually little!")
    1.42 +#endif
    1.43 +
    1.44 +void
    1.45 +PremultiplySurface(DataSourceSurface* srcSurface,
    1.46 +                   DataSourceSurface* destSurface)
    1.47 +{
    1.48 +  if (!destSurface)
    1.49 +    destSurface = srcSurface;
    1.50 +
    1.51 +  IntSize srcSize = srcSurface->GetSize();
    1.52 +  MOZ_ASSERT(srcSurface->GetFormat() == destSurface->GetFormat() &&
    1.53 +             srcSize.width  == destSurface->GetSize().width &&
    1.54 +             srcSize.height  == destSurface->GetSize().height &&
    1.55 +             srcSurface->Stride() == destSurface->Stride(),
    1.56 +             "Source and destination surfaces don't have identical characteristics");
    1.57 +
    1.58 +  MOZ_ASSERT(srcSurface->Stride() == srcSize.width * 4,
    1.59 +             "Source surface stride isn't tightly packed");
    1.60 +
    1.61 +  // Only premultiply ARGB32
    1.62 +  if (srcSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
    1.63 +    if (destSurface != srcSurface) {
    1.64 +      memcpy(destSurface->GetData(), srcSurface->GetData(),
    1.65 +             srcSurface->Stride() * srcSize.height);
    1.66 +    }
    1.67 +    return;
    1.68 +  }
    1.69 +
    1.70 +  uint8_t *src = srcSurface->GetData();
    1.71 +  uint8_t *dst = destSurface->GetData();
    1.72 +
    1.73 +  // Assert that our endian define is correct.
    1.74 +  ASSERT_ENDIAN();
    1.75 +
    1.76 +  uint32_t dim = srcSize.width * srcSize.height;
    1.77 +  for (uint32_t i = 0; i < dim; ++i) {
    1.78 +#ifdef MOZ_LITTLE_ENDIAN
    1.79 +    uint8_t b = *src++;
    1.80 +    uint8_t g = *src++;
    1.81 +    uint8_t r = *src++;
    1.82 +    uint8_t a = *src++;
    1.83 +
    1.84 +    *dst++ = PremultiplyValue(a, b);
    1.85 +    *dst++ = PremultiplyValue(a, g);
    1.86 +    *dst++ = PremultiplyValue(a, r);
    1.87 +    *dst++ = a;
    1.88 +#else
    1.89 +    uint8_t a = *src++;
    1.90 +    uint8_t r = *src++;
    1.91 +    uint8_t g = *src++;
    1.92 +    uint8_t b = *src++;
    1.93 +
    1.94 +    *dst++ = a;
    1.95 +    *dst++ = PremultiplyValue(a, r);
    1.96 +    *dst++ = PremultiplyValue(a, g);
    1.97 +    *dst++ = PremultiplyValue(a, b);
    1.98 +#endif
    1.99 +  }
   1.100 +}
   1.101 +
   1.102 +
   1.103 +}
   1.104 +}

mercurial