tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BufferTexture.cpp (18703B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "BufferTexture.h"
      8 
      9 #include <utility>
     10 
     11 #include "libyuv.h"
     12 #include "mozilla/fallible.h"
     13 #include "mozilla/gfx/2D.h"
     14 #include "mozilla/gfx/Logging.h"
     15 #include "mozilla/layers/CompositableForwarder.h"
     16 #include "mozilla/layers/ISurfaceAllocator.h"
     17 #include "mozilla/layers/ImageDataSerializer.h"
     18 #include "mozilla/layers/TextureForwarder.h"
     19 
     20 #include "gfxPlatform.h"
     21 
     22 #ifdef MOZ_WIDGET_GTK
     23 #  include "gfxPlatformGtk.h"
     24 #endif
     25 
     26 using mozilla::ipc::IShmemAllocator;
     27 
     28 namespace mozilla {
     29 namespace layers {
     30 
     31 class MemoryTextureData : public BufferTextureData {
     32 public:
     33  static MemoryTextureData* Create(gfx::IntSize aSize,
     34                                   gfx::SurfaceFormat aFormat,
     35                                   gfx::BackendType aMoz2DBackend,
     36                                   LayersBackend aLayersBackend,
     37                                   TextureFlags aFlags,
     38                                   TextureAllocationFlags aAllocFlags,
     39                                   IShmemAllocator* aAllocator);
     40 
     41  virtual TextureData* CreateSimilar(
     42      LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
     43      TextureFlags aFlags = TextureFlags::DEFAULT,
     44      TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
     45 
     46  virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
     47 
     48  virtual void Deallocate(LayersIPCChannel*) override;
     49 
     50  MemoryTextureData(const BufferDescriptor& aDesc,
     51                    gfx::BackendType aMoz2DBackend, uint8_t* aBuffer,
     52                    size_t aBufferSize, bool aAutoDeallocate = false,
     53                    bool aIsClear = false)
     54      : BufferTextureData(aDesc, aMoz2DBackend, aIsClear),
     55        mBuffer(aBuffer),
     56        mBufferSize(aBufferSize),
     57        mAutoDeallocate(aAutoDeallocate) {
     58    MOZ_ASSERT(aBuffer);
     59    MOZ_ASSERT(aBufferSize);
     60  }
     61 
     62  virtual ~MemoryTextureData() override {
     63    if (mAutoDeallocate) {
     64      Deallocate(nullptr);
     65    }
     66  }
     67 
     68  virtual uint8_t* GetBuffer() override { return mBuffer; }
     69 
     70  virtual size_t GetBufferSize() override { return mBufferSize; }
     71 
     72  TextureType GetTextureType() const override { return TextureType::Unknown; }
     73 
     74 protected:
     75  uint8_t* mBuffer;
     76  size_t mBufferSize;
     77  bool mAutoDeallocate;
     78 };
     79 
     80 class ShmemTextureData : public BufferTextureData {
     81 public:
     82  static ShmemTextureData* Create(gfx::IntSize aSize,
     83                                  gfx::SurfaceFormat aFormat,
     84                                  gfx::BackendType aMoz2DBackend,
     85                                  LayersBackend aLayersBackend,
     86                                  TextureFlags aFlags,
     87                                  TextureAllocationFlags aAllocFlags,
     88                                  IShmemAllocator* aAllocator);
     89 
     90  virtual TextureData* CreateSimilar(
     91      LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
     92      TextureFlags aFlags = TextureFlags::DEFAULT,
     93      TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
     94 
     95  virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
     96 
     97  virtual void Deallocate(LayersIPCChannel* aAllocator) override;
     98 
     99  ShmemTextureData(const BufferDescriptor& aDesc,
    100                   gfx::BackendType aMoz2DBackend, mozilla::ipc::Shmem aShmem,
    101                   bool aIsClear = false)
    102      : BufferTextureData(aDesc, aMoz2DBackend, aIsClear), mShmem(aShmem) {
    103    MOZ_ASSERT(mShmem.Size<uint8_t>());
    104  }
    105 
    106  virtual uint8_t* GetBuffer() override { return mShmem.get<uint8_t>(); }
    107 
    108  virtual size_t GetBufferSize() override { return mShmem.Size<uint8_t>(); }
    109 
    110 protected:
    111  mozilla::ipc::Shmem mShmem;
    112 };
    113 
    114 BufferTextureData* BufferTextureData::Create(
    115    gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
    116    gfx::BackendType aMoz2DBackend, LayersBackend aLayersBackend,
    117    TextureFlags aFlags, TextureAllocationFlags aAllocFlags,
    118    mozilla::ipc::IShmemAllocator* aAllocator, bool aIsSameProcess) {
    119  if (!aAllocator || aIsSameProcess) {
    120    return MemoryTextureData::Create(aSize, aFormat, aMoz2DBackend,
    121                                     aLayersBackend, aFlags, aAllocFlags,
    122                                     aAllocator);
    123  } else {
    124    return ShmemTextureData::Create(aSize, aFormat, aMoz2DBackend,
    125                                    aLayersBackend, aFlags, aAllocFlags,
    126                                    aAllocator);
    127  }
    128 }
    129 
    130 BufferTextureData* BufferTextureData::CreateInternal(
    131    LayersIPCChannel* aAllocator, const BufferDescriptor& aDesc,
    132    gfx::BackendType aMoz2DBackend, int32_t aBufferSize,
    133    TextureFlags aTextureFlags) {
    134  if (!aAllocator || aAllocator->IsSameProcess()) {
    135    uint8_t* buffer = new (fallible) uint8_t[aBufferSize];
    136    if (!buffer) {
    137      return nullptr;
    138    }
    139 
    140    GfxMemoryImageReporter::DidAlloc(buffer);
    141 
    142    return new MemoryTextureData(aDesc, aMoz2DBackend, buffer, aBufferSize);
    143  } else {
    144    ipc::Shmem shm;
    145    if (!aAllocator->AllocUnsafeShmem(aBufferSize, &shm)) {
    146      return nullptr;
    147    }
    148 
    149    bool isClear = aDesc.type() == BufferDescriptor::TRGBDescriptor &&
    150                   !IsOpaque(aDesc.get_RGBDescriptor().format());
    151    return new ShmemTextureData(aDesc, aMoz2DBackend, shm, isClear);
    152  }
    153 }
    154 
    155 BufferTextureData* BufferTextureData::CreateForYCbCr(
    156    KnowsCompositor* aAllocator, const gfx::IntRect& aDisplay,
    157    const gfx::IntSize& aYSize, uint32_t aYStride,
    158    const gfx::IntSize& aCbCrSize, uint32_t aCbCrStride, StereoMode aStereoMode,
    159    gfx::ColorDepth aColorDepth, gfx::YUVColorSpace aYUVColorSpace,
    160    gfx::ColorRange aColorRange, gfx::ChromaSubsampling aSubsampling,
    161    TextureFlags aTextureFlags) {
    162  uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(
    163      aYSize, aYStride, aCbCrSize, aCbCrStride);
    164  if (bufSize == 0) {
    165    return nullptr;
    166  }
    167 
    168  uint32_t yOffset;
    169  uint32_t cbOffset;
    170  uint32_t crOffset;
    171  ImageDataSerializer::ComputeYCbCrOffsets(aYStride, aYSize.height, aCbCrStride,
    172                                           aCbCrSize.height, yOffset, cbOffset,
    173                                           crOffset);
    174 
    175  YCbCrDescriptor descriptor =
    176      YCbCrDescriptor(aDisplay, aYSize, aYStride, aCbCrSize, aCbCrStride,
    177                      yOffset, cbOffset, crOffset, aStereoMode, aColorDepth,
    178                      aYUVColorSpace, aColorRange, aSubsampling);
    179 
    180  return CreateInternal(
    181      aAllocator ? aAllocator->GetTextureForwarder() : nullptr, descriptor,
    182      gfx::BackendType::NONE, bufSize, aTextureFlags);
    183 }
    184 
    185 void BufferTextureData::FillInfo(TextureData::Info& aInfo) const {
    186  aInfo.size = GetSize();
    187  aInfo.format = GetFormat();
    188  aInfo.hasSynchronization = false;
    189  aInfo.canExposeMappedData = true;
    190 
    191  switch (aInfo.format) {
    192    case gfx::SurfaceFormat::YUV420:
    193    case gfx::SurfaceFormat::UNKNOWN:
    194      aInfo.supportsMoz2D = false;
    195      break;
    196    default:
    197      aInfo.supportsMoz2D = true;
    198  }
    199 }
    200 
    201 gfx::IntSize BufferTextureData::GetSize() const {
    202  return ImageDataSerializer::SizeFromBufferDescriptor(mDescriptor);
    203 }
    204 
    205 gfx::IntRect BufferTextureData::GetPictureRect() const {
    206  return ImageDataSerializer::RectFromBufferDescriptor(mDescriptor);
    207 }
    208 
    209 Maybe<gfx::IntSize> BufferTextureData::GetYSize() const {
    210  return ImageDataSerializer::YSizeFromBufferDescriptor(mDescriptor);
    211 }
    212 
    213 Maybe<gfx::IntSize> BufferTextureData::GetCbCrSize() const {
    214  return ImageDataSerializer::CbCrSizeFromBufferDescriptor(mDescriptor);
    215 }
    216 
    217 Maybe<int32_t> BufferTextureData::GetYStride() const {
    218  return ImageDataSerializer::YStrideFromBufferDescriptor(mDescriptor);
    219 }
    220 
    221 Maybe<int32_t> BufferTextureData::GetCbCrStride() const {
    222  return ImageDataSerializer::CbCrStrideFromBufferDescriptor(mDescriptor);
    223 }
    224 
    225 Maybe<gfx::YUVColorSpace> BufferTextureData::GetYUVColorSpace() const {
    226  return ImageDataSerializer::YUVColorSpaceFromBufferDescriptor(mDescriptor);
    227 }
    228 
    229 Maybe<gfx::ColorDepth> BufferTextureData::GetColorDepth() const {
    230  return ImageDataSerializer::ColorDepthFromBufferDescriptor(mDescriptor);
    231 }
    232 
    233 Maybe<StereoMode> BufferTextureData::GetStereoMode() const {
    234  return ImageDataSerializer::StereoModeFromBufferDescriptor(mDescriptor);
    235 }
    236 
    237 Maybe<gfx::ChromaSubsampling> BufferTextureData::GetChromaSubsampling() const {
    238  return ImageDataSerializer::ChromaSubsamplingFromBufferDescriptor(
    239      mDescriptor);
    240 }
    241 
    242 gfx::SurfaceFormat BufferTextureData::GetFormat() const {
    243  return ImageDataSerializer::FormatFromBufferDescriptor(mDescriptor);
    244 }
    245 
    246 already_AddRefed<gfx::DrawTarget> BufferTextureData::BorrowDrawTarget() {
    247  if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
    248    return nullptr;
    249  }
    250 
    251  const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
    252 
    253  uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
    254  RefPtr<gfx::DrawTarget> dt;
    255  if (gfx::Factory::DoesBackendSupportDataDrawtarget(mMoz2DBackend)) {
    256    dt = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend, GetBuffer(),
    257                                               rgb.size(), stride, rgb.format(),
    258                                               true, mIsClear);
    259  }
    260  if (!dt) {
    261    // Fall back to supported platform backend.  Note that mMoz2DBackend
    262    // does not match the draw target type.
    263    dt = gfxPlatform::CreateDrawTargetForData(GetBuffer(), rgb.size(), stride,
    264                                              rgb.format(), true, mIsClear);
    265  }
    266 
    267  if (!dt) {
    268    gfxCriticalNote << "BorrowDrawTarget failure, original backend "
    269                    << (int)mMoz2DBackend;
    270  }
    271 
    272  return dt.forget();
    273 }
    274 
    275 bool BufferTextureData::BorrowMappedData(MappedTextureData& aData) {
    276  if (GetFormat() == gfx::SurfaceFormat::YUV420) {
    277    return false;
    278  }
    279 
    280  gfx::IntSize size = GetSize();
    281 
    282  aData.data = GetBuffer();
    283  aData.size = size;
    284  aData.format = GetFormat();
    285  aData.stride =
    286      ImageDataSerializer::ComputeRGBStride(aData.format, size.width);
    287  mIsClear = false;
    288 
    289  return true;
    290 }
    291 
    292 bool BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) {
    293  if (mDescriptor.type() != BufferDescriptor::TYCbCrDescriptor) {
    294    return false;
    295  }
    296 
    297  const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    298 
    299  uint8_t* data = GetBuffer();
    300  auto ySize = desc.ySize();
    301  auto cbCrSize = desc.cbCrSize();
    302 
    303  aMap.stereoMode = desc.stereoMode();
    304  aMap.metadata = nullptr;
    305  uint32_t bytesPerPixel =
    306      BytesPerPixel(SurfaceFormatForColorDepth(desc.colorDepth()));
    307 
    308  aMap.y.data = data + desc.yOffset();
    309  aMap.y.size = ySize;
    310  aMap.y.stride = desc.yStride();
    311  aMap.y.skip = 0;
    312  aMap.y.bytesPerPixel = bytesPerPixel;
    313 
    314  aMap.cb.data = data + desc.cbOffset();
    315  aMap.cb.size = cbCrSize;
    316  aMap.cb.stride = desc.cbCrStride();
    317  aMap.cb.skip = 0;
    318  aMap.cb.bytesPerPixel = bytesPerPixel;
    319 
    320  aMap.cr.data = data + desc.crOffset();
    321  aMap.cr.size = cbCrSize;
    322  aMap.cr.stride = desc.cbCrStride();
    323  aMap.cr.skip = 0;
    324  aMap.cr.bytesPerPixel = bytesPerPixel;
    325 
    326  return true;
    327 }
    328 
    329 bool BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) {
    330  if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
    331    return false;
    332  }
    333  const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
    334 
    335  uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
    336  RefPtr<gfx::DataSourceSurface> surface =
    337      gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), stride,
    338                                                    rgb.size(), rgb.format());
    339 
    340  if (!surface) {
    341    gfxCriticalError() << "Failed to get serializer as surface!";
    342    return false;
    343  }
    344 
    345  RefPtr<gfx::DataSourceSurface> srcSurf = aSurface->GetDataSurface();
    346 
    347  if (!srcSurf) {
    348    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (BT).";
    349    return false;
    350  }
    351 
    352  if (surface->GetSize() != srcSurf->GetSize() ||
    353      surface->GetFormat() != srcSurf->GetFormat()) {
    354    gfxCriticalError() << "Attempt to update texture client from a surface "
    355                          "with a different size or format (BT)! This: "
    356                       << surface->GetSize() << " " << surface->GetFormat()
    357                       << " Other: " << aSurface->GetSize() << " "
    358                       << aSurface->GetFormat();
    359    return false;
    360  }
    361 
    362  gfx::DataSourceSurface::MappedSurface sourceMap;
    363  gfx::DataSourceSurface::MappedSurface destMap;
    364  if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
    365    gfxCriticalError()
    366        << "Failed to map source surface for UpdateFromSurface (BT).";
    367    return false;
    368  }
    369 
    370  if (!surface->Map(gfx::DataSourceSurface::WRITE, &destMap)) {
    371    srcSurf->Unmap();
    372    gfxCriticalError()
    373        << "Failed to map destination surface for UpdateFromSurface.";
    374    return false;
    375  }
    376 
    377  for (int y = 0; y < srcSurf->GetSize().height; y++) {
    378    memcpy(destMap.mData + destMap.mStride * y,
    379           sourceMap.mData + sourceMap.mStride * y,
    380           srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
    381  }
    382 
    383  srcSurf->Unmap();
    384  surface->Unmap();
    385 
    386  mIsClear = false;
    387 
    388  return true;
    389 }
    390 
    391 bool MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
    392  MOZ_ASSERT(GetFormat() != gfx::SurfaceFormat::UNKNOWN);
    393  if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
    394    return false;
    395  }
    396 
    397  uintptr_t ptr = reinterpret_cast<uintptr_t>(mBuffer);
    398  aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(ptr));
    399 
    400  return true;
    401 }
    402 
    403 static bool InitBuffer(uint8_t* buf, size_t bufSize, gfx::SurfaceFormat aFormat,
    404                       TextureAllocationFlags aAllocFlags, bool aAlreadyZero) {
    405  if (!buf) {
    406    gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize
    407               << " bytes";
    408    return false;
    409  }
    410 
    411  if (aAllocFlags & ALLOC_CLEAR_BUFFER) {
    412    if (aFormat == gfx::SurfaceFormat::B8G8R8X8) {
    413      // Even though BGRX was requested, XRGB_UINT32 is what is meant,
    414      // so use 0xFF000000 to put alpha in the right place.
    415      libyuv::ARGBRect(buf, bufSize, 0, 0, bufSize / sizeof(uint32_t), 1,
    416                       0xFF000000);
    417    } else if (!aAlreadyZero) {
    418      memset(buf, 0, bufSize);
    419    }
    420  }
    421 
    422  return true;
    423 }
    424 
    425 MemoryTextureData* MemoryTextureData::Create(gfx::IntSize aSize,
    426                                             gfx::SurfaceFormat aFormat,
    427                                             gfx::BackendType aMoz2DBackend,
    428                                             LayersBackend aLayersBackend,
    429                                             TextureFlags aFlags,
    430                                             TextureAllocationFlags aAllocFlags,
    431                                             IShmemAllocator* aAllocator) {
    432  // Should have used CreateForYCbCr.
    433  MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV420);
    434 
    435  if (aSize.width <= 0 || aSize.height <= 0) {
    436    gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x"
    437               << aSize.height;
    438    return nullptr;
    439  }
    440 
    441  uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
    442  if (!bufSize) {
    443    return nullptr;
    444  }
    445 
    446  uint8_t* buf = new (fallible) uint8_t[bufSize];
    447  if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, false)) {
    448    return nullptr;
    449  }
    450 
    451  GfxMemoryImageReporter::DidAlloc(buf);
    452 
    453  BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat);
    454 
    455  // Remote textures are not managed by a texture client, so we need to ensure
    456  // that memory is freed when the owning MemoryTextureData goes away.
    457  bool autoDeallocate = !!(aFlags & TextureFlags::REMOTE_TEXTURE);
    458  bool isClear = (aAllocFlags & ALLOC_CLEAR_BUFFER) != 0;
    459  return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize,
    460                               autoDeallocate, isClear);
    461 }
    462 
    463 void MemoryTextureData::Deallocate(LayersIPCChannel*) {
    464  MOZ_ASSERT(mBuffer);
    465  GfxMemoryImageReporter::WillFree(mBuffer);
    466  delete[] mBuffer;
    467  mBuffer = nullptr;
    468 }
    469 
    470 TextureData* MemoryTextureData::CreateSimilar(
    471    LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
    472    TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const {
    473  return MemoryTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend,
    474                                   aLayersBackend, aFlags, aAllocFlags,
    475                                   aAllocator);
    476 }
    477 
    478 bool ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
    479  MOZ_ASSERT(GetFormat() != gfx::SurfaceFormat::UNKNOWN);
    480  if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
    481    return false;
    482  }
    483 
    484  aOutDescriptor =
    485      SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(std::move(mShmem)));
    486 
    487  return true;
    488 }
    489 
    490 ShmemTextureData* ShmemTextureData::Create(gfx::IntSize aSize,
    491                                           gfx::SurfaceFormat aFormat,
    492                                           gfx::BackendType aMoz2DBackend,
    493                                           LayersBackend aLayersBackend,
    494                                           TextureFlags aFlags,
    495                                           TextureAllocationFlags aAllocFlags,
    496                                           IShmemAllocator* aAllocator) {
    497  MOZ_ASSERT(aAllocator);
    498  // Should have used CreateForYCbCr.
    499  MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV420);
    500 
    501  if (!aAllocator) {
    502    return nullptr;
    503  }
    504 
    505  if (aSize.width <= 0 || aSize.height <= 0) {
    506    gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x"
    507               << aSize.height;
    508    return nullptr;
    509  }
    510 
    511  uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
    512  if (!bufSize) {
    513    return nullptr;
    514  }
    515 
    516  mozilla::ipc::Shmem shm;
    517  if (!aAllocator->AllocUnsafeShmem(bufSize, &shm)) {
    518    return nullptr;
    519  }
    520 
    521  uint8_t* buf = shm.get<uint8_t>();
    522  if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, true)) {
    523    return nullptr;
    524  }
    525 
    526  BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat);
    527  bool isClear = (aAllocFlags & ALLOC_CLEAR_BUFFER) || !IsOpaque(aFormat);
    528  return new ShmemTextureData(descriptor, aMoz2DBackend, shm, isClear);
    529 }
    530 
    531 TextureData* ShmemTextureData::CreateSimilar(
    532    LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
    533    TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const {
    534  return ShmemTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend,
    535                                  aLayersBackend, aFlags, aAllocFlags,
    536                                  aAllocator);
    537 }
    538 
    539 void ShmemTextureData::Deallocate(LayersIPCChannel* aAllocator) {
    540  if (!aAllocator) {
    541    gfxCriticalNote << "No allocator in ShmemTextureData::Deallocate";
    542    return;
    543  }
    544  aAllocator->DeallocShmem(mShmem);
    545 }
    546 
    547 }  // namespace layers
    548 }  // namespace mozilla