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.

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

mercurial