gfx/2d/SourceSurfaceD2D.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 "SourceSurfaceD2D.h"
     7 #include "DrawTargetD2D.h"
     8 #include "Logging.h"
     9 #include "Tools.h"
    11 namespace mozilla {
    12 namespace gfx {
    14 SourceSurfaceD2D::SourceSurfaceD2D()
    15 {
    16 }
    18 SourceSurfaceD2D::~SourceSurfaceD2D()
    19 {
    20   if (mBitmap) {
    21     DrawTargetD2D::mVRAMUsageSS -= GetByteSize();
    22   }
    23 }
    25 IntSize
    26 SourceSurfaceD2D::GetSize() const
    27 {
    28   return mSize;
    29 }
    31 SurfaceFormat
    32 SourceSurfaceD2D::GetFormat() const
    33 {
    34   return mFormat;
    35 }
    37 bool
    38 SourceSurfaceD2D::IsValid() const
    39 {
    40   return mDevice == Factory::GetDirect3D10Device();
    41 }
    43 TemporaryRef<DataSourceSurface>
    44 SourceSurfaceD2D::GetDataSurface()
    45 {
    46   RefPtr<DataSourceSurfaceD2D> result = new DataSourceSurfaceD2D(this);
    47   if (result->IsValid()) {
    48     return result;
    49   }
    50   return nullptr;
    51 }
    53 bool
    54 SourceSurfaceD2D::InitFromData(unsigned char *aData,
    55                                const IntSize &aSize,
    56                                int32_t aStride,
    57                                SurfaceFormat aFormat,
    58                                ID2D1RenderTarget *aRT)
    59 {
    60   HRESULT hr;
    62   mFormat = aFormat;
    63   mSize = aSize;
    65   if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
    66       (uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
    67     gfxDebug() << "Bitmap does not fit in texture.";
    68     return false;
    69   }
    71   D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
    72   hr = aRT->CreateBitmap(D2DIntSize(aSize), aData, aStride, props, byRef(mBitmap));
    74   if (FAILED(hr)) {
    75     gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hr;
    76     return false;
    77   }
    79   DrawTargetD2D::mVRAMUsageSS += GetByteSize();
    80   mDevice = Factory::GetDirect3D10Device();
    82   return true;
    83 }
    85 bool
    86 SourceSurfaceD2D::InitFromTexture(ID3D10Texture2D *aTexture,
    87                                   SurfaceFormat aFormat,
    88                                   ID2D1RenderTarget *aRT)
    89 {
    90   HRESULT hr;
    92   RefPtr<IDXGISurface> surf;
    94   hr = aTexture->QueryInterface((IDXGISurface**)&surf);
    96   if (FAILED(hr)) {
    97     gfxWarning() << "Failed to QI texture to surface. Code: " << hr;
    98     return false;
    99   }
   101   D3D10_TEXTURE2D_DESC desc;
   102   aTexture->GetDesc(&desc);
   104   mSize = IntSize(desc.Width, desc.Height);
   105   mFormat = aFormat;
   107   D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
   108   hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
   110   if (FAILED(hr)) {
   111     gfxWarning() << "Failed to create SharedBitmap. Code: " << hr;
   112     return false;
   113   }
   115   aTexture->GetDevice(byRef(mDevice));
   116   DrawTargetD2D::mVRAMUsageSS += GetByteSize();
   118   return true;
   119 }
   121 uint32_t
   122 SourceSurfaceD2D::GetByteSize() const
   123 {
   124   return mSize.width * mSize.height * BytesPerPixel(mFormat);
   125 }
   127 DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface)
   128   : mTexture(nullptr)
   129   , mFormat(aSourceSurface->mFormat)
   130   , mSize(aSourceSurface->mSize)
   131   , mMapped(false)
   132 {
   133   // We allocate ourselves a regular D3D surface (sourceTexture) and paint the
   134   // D2D bitmap into it via a DXGI render target. Then we need to copy
   135   // sourceTexture into a staging texture (mTexture), which we will lazily map
   136   // to get the data.
   138   CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height);
   139   desc.MipLevels = 1;
   140   desc.Usage = D3D10_USAGE_DEFAULT;
   141   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
   142   RefPtr<ID3D10Texture2D> sourceTexture;
   143   HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr,
   144                                                         byRef(sourceTexture));
   145   if (FAILED(hr)) {
   146     gfxWarning() << "Failed to create texture. Code: " << hr;
   147     return;
   148   }
   150   RefPtr<IDXGISurface> dxgiSurface;
   151   hr = sourceTexture->QueryInterface((IDXGISurface**)byRef(dxgiSurface));
   152   if (FAILED(hr)) {
   153     gfxWarning() << "Failed to create DXGI surface. Code: " << hr;
   154     return;
   155   }
   157   D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
   158             D2D1_RENDER_TARGET_TYPE_DEFAULT,
   159             D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
   161   RefPtr<ID2D1RenderTarget> renderTarget;
   162   hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
   163                                                                &rtProps,
   164                                                                byRef(renderTarget));
   165   if (FAILED(hr)) {
   166     gfxWarning() << "Failed to create render target. Code: " << hr;
   167     return;
   168   }
   170   renderTarget->BeginDraw();
   171   renderTarget->Clear(D2D1::ColorF(0, 0.0f));
   172   renderTarget->DrawBitmap(aSourceSurface->mBitmap,
   173                            D2D1::RectF(0, 0,
   174                                        Float(mSize.width),
   175                                        Float(mSize.height)));
   176   hr = renderTarget->EndDraw();
   177   if (FAILED(hr)) {
   178     gfxWarning() << "Failed to draw bitmap. Code: " << hr;
   179     return;
   180   }
   182   desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE;
   183   desc.Usage = D3D10_USAGE_STAGING;
   184   desc.BindFlags = 0;
   185   hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture));
   186   if (FAILED(hr)) {
   187     gfxWarning() << "Failed to create staging texture. Code: " << hr;
   188     mTexture = nullptr;
   189     return;
   190   }
   192   aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture);
   193 }
   195 DataSourceSurfaceD2D::~DataSourceSurfaceD2D()
   196 {
   197   if (mMapped) {
   198     mTexture->Unmap(0);
   199   }
   200 }
   202 unsigned char*
   203 DataSourceSurfaceD2D::GetData()
   204 {
   205   EnsureMappedTexture();
   206   if (!mMapped) {
   207     return nullptr;
   208   }
   210   return reinterpret_cast<unsigned char*>(mData.pData);
   211 }
   213 int32_t
   214 DataSourceSurfaceD2D::Stride()
   215 {
   216   EnsureMappedTexture();
   217   if (!mMapped) {
   218     return 0;
   219   }
   221   return mData.RowPitch;
   222 }
   224 IntSize
   225 DataSourceSurfaceD2D::GetSize() const
   226 {
   227   return mSize;
   228 }
   230 SurfaceFormat
   231 DataSourceSurfaceD2D::GetFormat() const
   232 {
   233   return mFormat;
   234 }
   236 bool
   237 DataSourceSurfaceD2D::Map(MapType aMapType, MappedSurface *aMappedSurface)
   238 {
   239   // DataSourceSurfaces used with the new Map API should not be used with GetData!!
   240   MOZ_ASSERT(!mMapped);
   241   MOZ_ASSERT(!mIsMapped);
   243   if (!mTexture) {
   244     return false;
   245   }
   247   D3D10_MAP mapType;
   249   if (aMapType == MapType::READ) {
   250     mapType = D3D10_MAP_READ;
   251   } else if (aMapType == MapType::WRITE) {
   252     mapType = D3D10_MAP_WRITE;
   253   } else {
   254     mapType = D3D10_MAP_READ_WRITE;
   255   }
   257   D3D10_MAPPED_TEXTURE2D map;
   259   HRESULT hr = mTexture->Map(0, mapType, 0, &map);
   261   if (FAILED(hr)) {
   262     gfxWarning() << "Texture map failed with code: " << hr;
   263     return false;
   264   }
   266   aMappedSurface->mData = (uint8_t*)map.pData;
   267   aMappedSurface->mStride = map.RowPitch;
   268   mIsMapped = true;
   270   return true;
   271 }
   273 void
   274 DataSourceSurfaceD2D::Unmap()
   275 {
   276   MOZ_ASSERT(mIsMapped);
   278   mIsMapped = false;
   279   mTexture->Unmap(0);
   280 }
   282 void
   283 DataSourceSurfaceD2D::EnsureMappedTexture()
   284 {
   285   // Do not use GetData() after having used Map!
   286   MOZ_ASSERT(!mIsMapped);
   288   if (mMapped ||
   289       !mTexture) {
   290     return;
   291   }
   293   HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mData);
   294   if (FAILED(hr)) {
   295     gfxWarning() << "Failed to map texture. Code: " << hr;
   296     mTexture = nullptr;
   297   } else {
   298     mMapped = true;
   299   }
   300 }
   302 }
   303 }

mercurial