gfx/2d/SourceSurfaceD2DTarget.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 "SourceSurfaceD2DTarget.h"
michael@0 7 #include "Logging.h"
michael@0 8 #include "DrawTargetD2D.h"
michael@0 9 #include "Tools.h"
michael@0 10
michael@0 11 #include <algorithm>
michael@0 12
michael@0 13 namespace mozilla {
michael@0 14 namespace gfx {
michael@0 15
michael@0 16 SourceSurfaceD2DTarget::SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget,
michael@0 17 ID3D10Texture2D* aTexture,
michael@0 18 SurfaceFormat aFormat)
michael@0 19 : mDrawTarget(aDrawTarget)
michael@0 20 , mTexture(aTexture)
michael@0 21 , mFormat(aFormat)
michael@0 22 , mOwnsCopy(false)
michael@0 23 {
michael@0 24 }
michael@0 25
michael@0 26 SourceSurfaceD2DTarget::~SourceSurfaceD2DTarget()
michael@0 27 {
michael@0 28 // We don't need to do anything special here to notify our mDrawTarget. It must
michael@0 29 // already have cleared its mSnapshot field, otherwise this object would
michael@0 30 // be kept alive.
michael@0 31 if (mOwnsCopy) {
michael@0 32 IntSize size = GetSize();
michael@0 33
michael@0 34 DrawTargetD2D::mVRAMUsageSS -= size.width * size.height * BytesPerPixel(mFormat);
michael@0 35 }
michael@0 36 }
michael@0 37
michael@0 38 IntSize
michael@0 39 SourceSurfaceD2DTarget::GetSize() const
michael@0 40 {
michael@0 41 D3D10_TEXTURE2D_DESC desc;
michael@0 42 mTexture->GetDesc(&desc);
michael@0 43
michael@0 44 return IntSize(desc.Width, desc.Height);
michael@0 45 }
michael@0 46
michael@0 47 SurfaceFormat
michael@0 48 SourceSurfaceD2DTarget::GetFormat() const
michael@0 49 {
michael@0 50 return mFormat;
michael@0 51 }
michael@0 52
michael@0 53 TemporaryRef<DataSourceSurface>
michael@0 54 SourceSurfaceD2DTarget::GetDataSurface()
michael@0 55 {
michael@0 56 RefPtr<DataSourceSurfaceD2DTarget> dataSurf =
michael@0 57 new DataSourceSurfaceD2DTarget(mFormat);
michael@0 58
michael@0 59 D3D10_TEXTURE2D_DESC desc;
michael@0 60 mTexture->GetDesc(&desc);
michael@0 61
michael@0 62 desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
michael@0 63 desc.Usage = D3D10_USAGE_STAGING;
michael@0 64 desc.BindFlags = 0;
michael@0 65 desc.MiscFlags = 0;
michael@0 66
michael@0 67 HRESULT hr = Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, byRef(dataSurf->mTexture));
michael@0 68
michael@0 69 if (FAILED(hr)) {
michael@0 70 gfxDebug() << "Failed to create staging texture for SourceSurface. Code: " << hr;
michael@0 71 return nullptr;
michael@0 72 }
michael@0 73 Factory::GetDirect3D10Device()->CopyResource(dataSurf->mTexture, mTexture);
michael@0 74
michael@0 75 return dataSurf;
michael@0 76 }
michael@0 77
michael@0 78 void*
michael@0 79 SourceSurfaceD2DTarget::GetNativeSurface(NativeSurfaceType aType)
michael@0 80 {
michael@0 81 if (aType == NativeSurfaceType::D3D10_TEXTURE) {
michael@0 82 return static_cast<void*>(mTexture.get());
michael@0 83 }
michael@0 84 return nullptr;
michael@0 85 }
michael@0 86
michael@0 87 ID3D10ShaderResourceView*
michael@0 88 SourceSurfaceD2DTarget::GetSRView()
michael@0 89 {
michael@0 90 if (mSRView) {
michael@0 91 return mSRView;
michael@0 92 }
michael@0 93
michael@0 94 HRESULT hr = Factory::GetDirect3D10Device()->CreateShaderResourceView(mTexture, nullptr, byRef(mSRView));
michael@0 95
michael@0 96 if (FAILED(hr)) {
michael@0 97 gfxWarning() << "Failed to create ShaderResourceView. Code: " << hr;
michael@0 98 }
michael@0 99
michael@0 100 return mSRView;
michael@0 101 }
michael@0 102
michael@0 103 void
michael@0 104 SourceSurfaceD2DTarget::DrawTargetWillChange()
michael@0 105 {
michael@0 106 RefPtr<ID3D10Texture2D> oldTexture = mTexture;
michael@0 107
michael@0 108 D3D10_TEXTURE2D_DESC desc;
michael@0 109 mTexture->GetDesc(&desc);
michael@0 110
michael@0 111 // Our original texture might implement the keyed mutex flag. We shouldn't
michael@0 112 // need that here. We actually specifically don't want it since we don't lock
michael@0 113 // our texture for usage!
michael@0 114 desc.MiscFlags = 0;
michael@0 115
michael@0 116 // Get a copy of the surface data so the content at snapshot time was saved.
michael@0 117 Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, byRef(mTexture));
michael@0 118 Factory::GetDirect3D10Device()->CopyResource(mTexture, oldTexture);
michael@0 119
michael@0 120 mBitmap = nullptr;
michael@0 121
michael@0 122 DrawTargetD2D::mVRAMUsageSS += desc.Width * desc.Height * BytesPerPixel(mFormat);
michael@0 123 mOwnsCopy = true;
michael@0 124
michael@0 125 // We now no longer depend on the source surface content remaining the same.
michael@0 126 MarkIndependent();
michael@0 127 }
michael@0 128
michael@0 129 ID2D1Bitmap*
michael@0 130 SourceSurfaceD2DTarget::GetBitmap(ID2D1RenderTarget *aRT)
michael@0 131 {
michael@0 132 if (mBitmap) {
michael@0 133 return mBitmap;
michael@0 134 }
michael@0 135
michael@0 136 HRESULT hr;
michael@0 137 D3D10_TEXTURE2D_DESC desc;
michael@0 138 mTexture->GetDesc(&desc);
michael@0 139
michael@0 140 IntSize size(desc.Width, desc.Height);
michael@0 141
michael@0 142 RefPtr<IDXGISurface> surf;
michael@0 143 hr = mTexture->QueryInterface((IDXGISurface**)byRef(surf));
michael@0 144
michael@0 145 if (FAILED(hr)) {
michael@0 146 gfxWarning() << "Failed to query interface texture to DXGISurface. Code: " << hr;
michael@0 147 return nullptr;
michael@0 148 }
michael@0 149
michael@0 150 D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(mFormat));
michael@0 151 hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
michael@0 152
michael@0 153 if (FAILED(hr)) {
michael@0 154 // This seems to happen for SurfaceFormat::A8 sometimes...
michael@0 155 hr = aRT->CreateBitmap(D2D1::SizeU(desc.Width, desc.Height),
michael@0 156 D2D1::BitmapProperties(D2DPixelFormat(mFormat)),
michael@0 157 byRef(mBitmap));
michael@0 158
michael@0 159 if (FAILED(hr)) {
michael@0 160 gfxWarning() << "Failed in CreateBitmap. Code: " << hr;
michael@0 161 return nullptr;
michael@0 162 }
michael@0 163
michael@0 164 RefPtr<ID2D1RenderTarget> rt;
michael@0 165
michael@0 166 if (mDrawTarget) {
michael@0 167 rt = mDrawTarget->mRT;
michael@0 168 }
michael@0 169
michael@0 170 if (!rt) {
michael@0 171 // Okay, we already separated from our drawtarget. And we're an A8
michael@0 172 // surface the only way we can get to a bitmap is by creating a
michael@0 173 // a rendertarget and from there copying to a bitmap! Terrible!
michael@0 174 RefPtr<IDXGISurface> surface;
michael@0 175
michael@0 176 hr = mTexture->QueryInterface((IDXGISurface**)byRef(surface));
michael@0 177
michael@0 178 if (FAILED(hr)) {
michael@0 179 gfxWarning() << "Failed to QI texture to surface.";
michael@0 180 return nullptr;
michael@0 181 }
michael@0 182
michael@0 183 D2D1_RENDER_TARGET_PROPERTIES props =
michael@0 184 D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2DPixelFormat(mFormat));
michael@0 185 hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(surface, props, byRef(rt));
michael@0 186
michael@0 187 if (FAILED(hr)) {
michael@0 188 gfxWarning() << "Failed to create D2D render target for texture.";
michael@0 189 return nullptr;
michael@0 190 }
michael@0 191 }
michael@0 192
michael@0 193 mBitmap->CopyFromRenderTarget(nullptr, rt, nullptr);
michael@0 194 return mBitmap;
michael@0 195 }
michael@0 196
michael@0 197 return mBitmap;
michael@0 198 }
michael@0 199
michael@0 200 void
michael@0 201 SourceSurfaceD2DTarget::MarkIndependent()
michael@0 202 {
michael@0 203 if (mDrawTarget) {
michael@0 204 MOZ_ASSERT(mDrawTarget->mSnapshot == this);
michael@0 205 mDrawTarget->mSnapshot = nullptr;
michael@0 206 mDrawTarget = nullptr;
michael@0 207 }
michael@0 208 }
michael@0 209
michael@0 210 DataSourceSurfaceD2DTarget::DataSourceSurfaceD2DTarget(SurfaceFormat aFormat)
michael@0 211 : mFormat(aFormat)
michael@0 212 , mMapped(false)
michael@0 213 {
michael@0 214 }
michael@0 215
michael@0 216 DataSourceSurfaceD2DTarget::~DataSourceSurfaceD2DTarget()
michael@0 217 {
michael@0 218 if (mMapped) {
michael@0 219 mTexture->Unmap(0);
michael@0 220 }
michael@0 221 }
michael@0 222
michael@0 223 IntSize
michael@0 224 DataSourceSurfaceD2DTarget::GetSize() const
michael@0 225 {
michael@0 226 D3D10_TEXTURE2D_DESC desc;
michael@0 227 mTexture->GetDesc(&desc);
michael@0 228
michael@0 229 return IntSize(desc.Width, desc.Height);
michael@0 230 }
michael@0 231
michael@0 232 SurfaceFormat
michael@0 233 DataSourceSurfaceD2DTarget::GetFormat() const
michael@0 234 {
michael@0 235 return mFormat;
michael@0 236 }
michael@0 237
michael@0 238 uint8_t*
michael@0 239 DataSourceSurfaceD2DTarget::GetData()
michael@0 240 {
michael@0 241 EnsureMapped();
michael@0 242
michael@0 243 return (unsigned char*)mMap.pData;
michael@0 244 }
michael@0 245
michael@0 246 int32_t
michael@0 247 DataSourceSurfaceD2DTarget::Stride()
michael@0 248 {
michael@0 249 EnsureMapped();
michael@0 250 return mMap.RowPitch;
michael@0 251 }
michael@0 252
michael@0 253 bool
michael@0 254 DataSourceSurfaceD2DTarget::Map(MapType aMapType, MappedSurface *aMappedSurface)
michael@0 255 {
michael@0 256 // DataSourceSurfaces used with the new Map API should not be used with GetData!!
michael@0 257 MOZ_ASSERT(!mMapped);
michael@0 258 MOZ_ASSERT(!mIsMapped);
michael@0 259
michael@0 260 if (!mTexture) {
michael@0 261 return false;
michael@0 262 }
michael@0 263
michael@0 264 D3D10_MAP mapType;
michael@0 265
michael@0 266 if (aMapType == MapType::READ) {
michael@0 267 mapType = D3D10_MAP_READ;
michael@0 268 } else if (aMapType == MapType::WRITE) {
michael@0 269 mapType = D3D10_MAP_WRITE;
michael@0 270 } else {
michael@0 271 mapType = D3D10_MAP_READ_WRITE;
michael@0 272 }
michael@0 273
michael@0 274 D3D10_MAPPED_TEXTURE2D map;
michael@0 275
michael@0 276 HRESULT hr = mTexture->Map(0, mapType, 0, &map);
michael@0 277
michael@0 278 if (FAILED(hr)) {
michael@0 279 gfxWarning() << "Texture map failed with code: " << hr;
michael@0 280 return false;
michael@0 281 }
michael@0 282
michael@0 283 aMappedSurface->mData = (uint8_t*)map.pData;
michael@0 284 aMappedSurface->mStride = map.RowPitch;
michael@0 285 mIsMapped = true;
michael@0 286
michael@0 287 return true;
michael@0 288 }
michael@0 289
michael@0 290 void
michael@0 291 DataSourceSurfaceD2DTarget::Unmap()
michael@0 292 {
michael@0 293 MOZ_ASSERT(mIsMapped);
michael@0 294
michael@0 295 mIsMapped = false;
michael@0 296 mTexture->Unmap(0);
michael@0 297 }
michael@0 298
michael@0 299 void
michael@0 300 DataSourceSurfaceD2DTarget::EnsureMapped()
michael@0 301 {
michael@0 302 // Do not use GetData() after having used Map!
michael@0 303 MOZ_ASSERT(!mIsMapped);
michael@0 304 if (!mMapped) {
michael@0 305 HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mMap);
michael@0 306 if (FAILED(hr)) {
michael@0 307 gfxWarning() << "Failed to map texture to memory. Code: " << hr;
michael@0 308 return;
michael@0 309 }
michael@0 310 mMapped = true;
michael@0 311 }
michael@0 312 }
michael@0 313
michael@0 314 }
michael@0 315 }

mercurial