gfx/2d/SourceSurfaceD2D.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial