gfx/layers/D3D9SurfaceImage.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 "D3D9SurfaceImage.h"
michael@0 7 #include "gfx2DGlue.h"
michael@0 8 #include "mozilla/layers/TextureD3D9.h"
michael@0 9 #include "mozilla/gfx/Types.h"
michael@0 10
michael@0 11 namespace mozilla {
michael@0 12 namespace layers {
michael@0 13
michael@0 14
michael@0 15 D3D9SurfaceImage::D3D9SurfaceImage()
michael@0 16 : Image(nullptr, ImageFormat::D3D9_RGB32_TEXTURE)
michael@0 17 , mSize(0, 0)
michael@0 18 {}
michael@0 19
michael@0 20 D3D9SurfaceImage::~D3D9SurfaceImage() {}
michael@0 21
michael@0 22 HRESULT
michael@0 23 D3D9SurfaceImage::SetData(const Data& aData)
michael@0 24 {
michael@0 25 NS_ENSURE_TRUE(aData.mSurface, E_POINTER);
michael@0 26 HRESULT hr;
michael@0 27 RefPtr<IDirect3DSurface9> surface = aData.mSurface;
michael@0 28
michael@0 29 RefPtr<IDirect3DDevice9> device;
michael@0 30 hr = surface->GetDevice(byRef(device));
michael@0 31 NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL);
michael@0 32
michael@0 33 RefPtr<IDirect3D9> d3d9;
michael@0 34 hr = device->GetDirect3D(byRef(d3d9));
michael@0 35 NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL);
michael@0 36
michael@0 37 D3DSURFACE_DESC desc;
michael@0 38 surface->GetDesc(&desc);
michael@0 39 // Ensure we can convert the textures format to RGB conversion
michael@0 40 // in StretchRect. Fail if we can't.
michael@0 41 hr = d3d9->CheckDeviceFormatConversion(D3DADAPTER_DEFAULT,
michael@0 42 D3DDEVTYPE_HAL,
michael@0 43 desc.Format,
michael@0 44 D3DFMT_X8R8G8B8);
michael@0 45 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 46
michael@0 47 // DXVA surfaces aren't created sharable, so we need to copy the surface
michael@0 48 // to a sharable texture to that it's accessible to the layer manager's
michael@0 49 // device.
michael@0 50 const nsIntRect& region = aData.mRegion;
michael@0 51 RefPtr<IDirect3DTexture9> texture;
michael@0 52 HANDLE shareHandle = nullptr;
michael@0 53 hr = device->CreateTexture(region.width,
michael@0 54 region.height,
michael@0 55 1,
michael@0 56 D3DUSAGE_RENDERTARGET,
michael@0 57 D3DFMT_X8R8G8B8,
michael@0 58 D3DPOOL_DEFAULT,
michael@0 59 byRef(texture),
michael@0 60 &shareHandle);
michael@0 61 NS_ENSURE_TRUE(SUCCEEDED(hr) && shareHandle, hr);
michael@0 62
michael@0 63 // Copy the image onto the texture, preforming YUV -> RGB conversion if necessary.
michael@0 64 RefPtr<IDirect3DSurface9> textureSurface;
michael@0 65 hr = texture->GetSurfaceLevel(0, byRef(textureSurface));
michael@0 66 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 67
michael@0 68 // Stash the surface description for later use.
michael@0 69 textureSurface->GetDesc(&mDesc);
michael@0 70
michael@0 71 RECT src = { region.x, region.y, region.x+region.width, region.y+region.height };
michael@0 72 hr = device->StretchRect(surface, &src, textureSurface, nullptr, D3DTEXF_NONE);
michael@0 73 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 74
michael@0 75 // Flush the draw command now, so that by the time we come to draw this
michael@0 76 // image, we're less likely to need to wait for the draw operation to
michael@0 77 // complete.
michael@0 78 RefPtr<IDirect3DQuery9> query;
michael@0 79 hr = device->CreateQuery(D3DQUERYTYPE_EVENT, byRef(query));
michael@0 80 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 81 hr = query->Issue(D3DISSUE_END);
michael@0 82 NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
michael@0 83
michael@0 84 mTexture = texture;
michael@0 85 mShareHandle = shareHandle;
michael@0 86 mSize = gfx::IntSize(region.width, region.height);
michael@0 87 mQuery = query;
michael@0 88
michael@0 89 return S_OK;
michael@0 90 }
michael@0 91
michael@0 92 void
michael@0 93 D3D9SurfaceImage::EnsureSynchronized()
michael@0 94 {
michael@0 95 if (!mQuery) {
michael@0 96 // Not setup, or already synchronized.
michael@0 97 return;
michael@0 98 }
michael@0 99 int iterations = 0;
michael@0 100 while (iterations < 10 && S_FALSE == mQuery->GetData(nullptr, 0, D3DGETDATA_FLUSH)) {
michael@0 101 Sleep(1);
michael@0 102 iterations++;
michael@0 103 }
michael@0 104 mQuery = nullptr;
michael@0 105 }
michael@0 106
michael@0 107 HANDLE
michael@0 108 D3D9SurfaceImage::GetShareHandle()
michael@0 109 {
michael@0 110 // Ensure the image has completed its synchronization,
michael@0 111 // and safe to used by the caller on another device.
michael@0 112 EnsureSynchronized();
michael@0 113 return mShareHandle;
michael@0 114 }
michael@0 115
michael@0 116 const D3DSURFACE_DESC&
michael@0 117 D3D9SurfaceImage::GetDesc() const
michael@0 118 {
michael@0 119 return mDesc;
michael@0 120 }
michael@0 121
michael@0 122 gfx::IntSize
michael@0 123 D3D9SurfaceImage::GetSize()
michael@0 124 {
michael@0 125 return mSize;
michael@0 126 }
michael@0 127
michael@0 128 TextureClient*
michael@0 129 D3D9SurfaceImage::GetTextureClient(CompositableClient* aClient)
michael@0 130 {
michael@0 131 EnsureSynchronized();
michael@0 132 if (!mTextureClient) {
michael@0 133 RefPtr<SharedTextureClientD3D9> textureClient =
michael@0 134 new SharedTextureClientD3D9(gfx::SurfaceFormat::B8G8R8X8, TEXTURE_FLAGS_DEFAULT);
michael@0 135 textureClient->InitWith(mTexture, mShareHandle, mDesc);
michael@0 136 mTextureClient = textureClient;
michael@0 137 }
michael@0 138 return mTextureClient;
michael@0 139 }
michael@0 140
michael@0 141 TemporaryRef<gfx::SourceSurface>
michael@0 142 D3D9SurfaceImage::GetAsSourceSurface()
michael@0 143 {
michael@0 144 NS_ENSURE_TRUE(mTexture, nullptr);
michael@0 145
michael@0 146 HRESULT hr;
michael@0 147 RefPtr<gfx::DataSourceSurface> surface = gfx::Factory::CreateDataSourceSurface(mSize, gfx::SurfaceFormat::B8G8R8X8);
michael@0 148
michael@0 149 if (!surface) {
michael@0 150 NS_WARNING("Failed to created SourceSurface for D3D9SurfaceImage.");
michael@0 151 return nullptr;
michael@0 152 }
michael@0 153
michael@0 154 // Ensure that the texture is ready to be used.
michael@0 155 EnsureSynchronized();
michael@0 156
michael@0 157 // Readback the texture from GPU memory into system memory, so that
michael@0 158 // we can copy it into the Cairo image. This is expensive.
michael@0 159 RefPtr<IDirect3DSurface9> textureSurface;
michael@0 160 hr = mTexture->GetSurfaceLevel(0, byRef(textureSurface));
michael@0 161 NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
michael@0 162
michael@0 163 RefPtr<IDirect3DDevice9> device;
michael@0 164 hr = mTexture->GetDevice(byRef(device));
michael@0 165 NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
michael@0 166
michael@0 167 RefPtr<IDirect3DSurface9> systemMemorySurface;
michael@0 168 hr = device->CreateOffscreenPlainSurface(mDesc.Width,
michael@0 169 mDesc.Height,
michael@0 170 D3DFMT_X8R8G8B8,
michael@0 171 D3DPOOL_SYSTEMMEM,
michael@0 172 byRef(systemMemorySurface),
michael@0 173 0);
michael@0 174 NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
michael@0 175
michael@0 176 hr = device->GetRenderTargetData(textureSurface, systemMemorySurface);
michael@0 177 NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
michael@0 178
michael@0 179 D3DLOCKED_RECT rect;
michael@0 180 hr = systemMemorySurface->LockRect(&rect, nullptr, 0);
michael@0 181 NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
michael@0 182
michael@0 183 gfx::DataSourceSurface::MappedSurface mappedSurface;
michael@0 184 if (!surface->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) {
michael@0 185 systemMemorySurface->UnlockRect();
michael@0 186 return nullptr;
michael@0 187 }
michael@0 188
michael@0 189 const unsigned char* src = (const unsigned char*)(rect.pBits);
michael@0 190 const unsigned srcPitch = rect.Pitch;
michael@0 191 for (int y = 0; y < mSize.height; y++) {
michael@0 192 memcpy(mappedSurface.mData + mappedSurface.mStride * y,
michael@0 193 (unsigned char*)(src) + srcPitch * y,
michael@0 194 mSize.width * 4);
michael@0 195 }
michael@0 196
michael@0 197 systemMemorySurface->UnlockRect();
michael@0 198 surface->Unmap();
michael@0 199
michael@0 200 return surface;
michael@0 201 }
michael@0 202
michael@0 203 } /* layers */
michael@0 204 } /* mozilla */

mercurial