gfx/layers/ipc/SharedPlanarYCbCrImage.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.

michael@0 1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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 #include "SharedPlanarYCbCrImage.h"
michael@0 7 #include <stddef.h> // for size_t
michael@0 8 #include <stdio.h> // for printf
michael@0 9 #include "gfx2DGlue.h" // for Moz2D transition helpers
michael@0 10 #include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc
michael@0 11 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
michael@0 12 #include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV
michael@0 13 #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
michael@0 14 #include "mozilla/layers/ImageClient.h" // for ImageClient
michael@0 15 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
michael@0 16 #include "mozilla/layers/TextureClient.h" // for BufferTextureClient, etc
michael@0 17 #include "mozilla/layers/YCbCrImageDataSerializer.h"
michael@0 18 #include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
michael@0 19 #include "mozilla/mozalloc.h" // for operator delete
michael@0 20 #include "nsISupportsImpl.h" // for Image::AddRef
michael@0 21 #include "mozilla/ipc/Shmem.h"
michael@0 22
michael@0 23 namespace mozilla {
michael@0 24 namespace layers {
michael@0 25
michael@0 26 using namespace mozilla::ipc;
michael@0 27
michael@0 28 SharedPlanarYCbCrImage::SharedPlanarYCbCrImage(ImageClient* aCompositable)
michael@0 29 : PlanarYCbCrImage(nullptr)
michael@0 30 , mCompositable(aCompositable)
michael@0 31 {
michael@0 32 mTextureClient = aCompositable->CreateBufferTextureClient(gfx::SurfaceFormat::YUV);
michael@0 33 MOZ_COUNT_CTOR(SharedPlanarYCbCrImage);
michael@0 34 }
michael@0 35
michael@0 36 SharedPlanarYCbCrImage::~SharedPlanarYCbCrImage() {
michael@0 37 MOZ_COUNT_DTOR(SharedPlanarYCbCrImage);
michael@0 38
michael@0 39 if (mCompositable->GetAsyncID() != 0 &&
michael@0 40 !InImageBridgeChildThread()) {
michael@0 41 ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient.forget().drop());
michael@0 42 ImageBridgeChild::DispatchReleaseImageClient(mCompositable.forget().drop());
michael@0 43 }
michael@0 44 }
michael@0 45
michael@0 46 size_t
michael@0 47 SharedPlanarYCbCrImage::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
michael@0 48 {
michael@0 49 // NB: Explicitly skipping mTextureClient, the memory is already reported
michael@0 50 // at time of allocation in GfxMemoryImageReporter.
michael@0 51 // Not owned:
michael@0 52 // - mCompositable
michael@0 53 size_t size = PlanarYCbCrImage::SizeOfExcludingThis(aMallocSizeOf);
michael@0 54 return size;
michael@0 55 }
michael@0 56
michael@0 57 TextureClient*
michael@0 58 SharedPlanarYCbCrImage::GetTextureClient(CompositableClient* aClient)
michael@0 59 {
michael@0 60 return mTextureClient.get();
michael@0 61 }
michael@0 62
michael@0 63 uint8_t*
michael@0 64 SharedPlanarYCbCrImage::GetBuffer()
michael@0 65 {
michael@0 66 return mTextureClient->GetBuffer();
michael@0 67 }
michael@0 68
michael@0 69 TemporaryRef<gfx::SourceSurface>
michael@0 70 SharedPlanarYCbCrImage::GetAsSourceSurface()
michael@0 71 {
michael@0 72 if (!mTextureClient->IsAllocated()) {
michael@0 73 NS_WARNING("Can't get as surface");
michael@0 74 return nullptr;
michael@0 75 }
michael@0 76 return PlanarYCbCrImage::GetAsSourceSurface();
michael@0 77 }
michael@0 78
michael@0 79 void
michael@0 80 SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
michael@0 81 {
michael@0 82 // If mShmem has not been allocated (through Allocate(aData)), allocate it.
michael@0 83 // This code path is slower than the one used when Allocate has been called
michael@0 84 // since it will trigger a full copy.
michael@0 85 if (!mTextureClient->IsAllocated()) {
michael@0 86 Data data = aData;
michael@0 87 if (!Allocate(data)) {
michael@0 88 NS_WARNING("SharedPlanarYCbCrImage::SetData failed to allocate");
michael@0 89 return;
michael@0 90 }
michael@0 91 }
michael@0 92
michael@0 93 MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr());
michael@0 94 if (!mTextureClient->Lock(OPEN_WRITE_ONLY)) {
michael@0 95 MOZ_ASSERT(false, "Failed to lock the texture.");
michael@0 96 return;
michael@0 97 }
michael@0 98 TextureClientAutoUnlock unlock(mTextureClient);
michael@0 99 if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) {
michael@0 100 MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
michael@0 101 return;
michael@0 102 }
michael@0 103 // do not set mBuffer like in PlanarYCbCrImage because the later
michael@0 104 // will try to manage this memory without knowing it belongs to a
michael@0 105 // shmem.
michael@0 106 mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize,
michael@0 107 mData.mCbCrSize);
michael@0 108 mSize = mData.mPicSize;
michael@0 109
michael@0 110 YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
michael@0 111 mData.mYChannel = serializer.GetYData();
michael@0 112 mData.mCbChannel = serializer.GetCbData();
michael@0 113 mData.mCrChannel = serializer.GetCrData();
michael@0 114 mTextureClient->MarkImmutable();
michael@0 115 }
michael@0 116
michael@0 117 // needs to be overriden because the parent class sets mBuffer which we
michael@0 118 // do not want to happen.
michael@0 119 uint8_t*
michael@0 120 SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
michael@0 121 {
michael@0 122 NS_ABORT_IF_FALSE(!mTextureClient->IsAllocated(), "This image already has allocated data");
michael@0 123 size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aSize);
michael@0 124
michael@0 125 // get new buffer _without_ setting mBuffer.
michael@0 126 if (!mTextureClient->Allocate(size)) {
michael@0 127 return nullptr;
michael@0 128 }
michael@0 129
michael@0 130 // update buffer size
michael@0 131 mBufferSize = size;
michael@0 132
michael@0 133 YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
michael@0 134 return serializer.GetData();
michael@0 135 }
michael@0 136
michael@0 137 void
michael@0 138 SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
michael@0 139 {
michael@0 140 mData = aData;
michael@0 141 mSize = aData.mPicSize;
michael@0 142 /* SetDataNoCopy is used to update YUV plane offsets without (re)allocating
michael@0 143 * memory previously allocated with AllocateAndGetNewBuffer().
michael@0 144 * serializer.GetData() returns the address of the memory previously allocated
michael@0 145 * with AllocateAndGetNewBuffer(), that we subtract from the Y, Cb, Cr
michael@0 146 * channels to compute 0-based offsets to pass to InitializeBufferInfo.
michael@0 147 */
michael@0 148 YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
michael@0 149 uint8_t *base = serializer.GetData();
michael@0 150 uint32_t yOffset = aData.mYChannel - base;
michael@0 151 uint32_t cbOffset = aData.mCbChannel - base;
michael@0 152 uint32_t crOffset = aData.mCrChannel - base;
michael@0 153 serializer.InitializeBufferInfo(yOffset,
michael@0 154 cbOffset,
michael@0 155 crOffset,
michael@0 156 aData.mYStride,
michael@0 157 aData.mCbCrStride,
michael@0 158 aData.mYSize,
michael@0 159 aData.mCbCrSize,
michael@0 160 aData.mStereoMode);
michael@0 161 }
michael@0 162
michael@0 163 uint8_t*
michael@0 164 SharedPlanarYCbCrImage::AllocateBuffer(uint32_t aSize)
michael@0 165 {
michael@0 166 NS_ABORT_IF_FALSE(!mTextureClient->IsAllocated(),
michael@0 167 "This image already has allocated data");
michael@0 168 if (!mTextureClient->Allocate(aSize)) {
michael@0 169 return nullptr;
michael@0 170 }
michael@0 171 return mTextureClient->GetBuffer();
michael@0 172 }
michael@0 173
michael@0 174 bool
michael@0 175 SharedPlanarYCbCrImage::IsValid() {
michael@0 176 return mTextureClient->IsAllocated();
michael@0 177 }
michael@0 178
michael@0 179 bool
michael@0 180 SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
michael@0 181 {
michael@0 182 NS_ABORT_IF_FALSE(!mTextureClient->IsAllocated(),
michael@0 183 "This image already has allocated data");
michael@0 184
michael@0 185 size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aData.mYSize,
michael@0 186 aData.mCbCrSize);
michael@0 187
michael@0 188 if (AllocateBuffer(static_cast<uint32_t>(size)) == nullptr) {
michael@0 189 return false;
michael@0 190 }
michael@0 191
michael@0 192 YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
michael@0 193 serializer.InitializeBufferInfo(aData.mYSize,
michael@0 194 aData.mCbCrSize,
michael@0 195 aData.mStereoMode);
michael@0 196 MOZ_ASSERT(serializer.IsValid());
michael@0 197
michael@0 198 aData.mYChannel = serializer.GetYData();
michael@0 199 aData.mCbChannel = serializer.GetCbData();
michael@0 200 aData.mCrChannel = serializer.GetCrData();
michael@0 201
michael@0 202 // copy some of aData's values in mData (most of them)
michael@0 203 mData.mYChannel = aData.mYChannel;
michael@0 204 mData.mCbChannel = aData.mCbChannel;
michael@0 205 mData.mCrChannel = aData.mCrChannel;
michael@0 206 mData.mYSize = aData.mYSize;
michael@0 207 mData.mCbCrSize = aData.mCbCrSize;
michael@0 208 mData.mPicX = aData.mPicX;
michael@0 209 mData.mPicY = aData.mPicY;
michael@0 210 mData.mPicSize = aData.mPicSize;
michael@0 211 mData.mStereoMode = aData.mStereoMode;
michael@0 212 // those members are not always equal to aData's, due to potentially different
michael@0 213 // packing.
michael@0 214 mData.mYSkip = 0;
michael@0 215 mData.mCbSkip = 0;
michael@0 216 mData.mCrSkip = 0;
michael@0 217 mData.mYStride = mData.mYSize.width;
michael@0 218 mData.mCbCrStride = mData.mCbCrSize.width;
michael@0 219
michael@0 220 return true;
michael@0 221 }
michael@0 222
michael@0 223 } // namespace
michael@0 224 } // namespace

mercurial