gecko-dev/gfx/2d/SourceSurfaceD2DTarget.cpp
Ryan VanderMeulen 606e8823ff Backed out 11 changesets (bug 1083101) for causing mass Windows 7 test failures.
Backed out changeset 42d192dbf938 (bug 1083101)
Backed out changeset 0a6cc12c33d7 (bug 1083101)
Backed out changeset b82291c07e0e (bug 1083101)
Backed out changeset 2d32462f6c58 (bug 1083101)
Backed out changeset c234e70021a7 (bug 1083101)
Backed out changeset 23a3870672ae (bug 1083101)
Backed out changeset 78f3c70cf1cb (bug 1083101)
Backed out changeset 86f55d9695f0 (bug 1083101)
Backed out changeset 6b8940305079 (bug 1083101)
Backed out changeset 5efc1e52e4e9 (bug 1083101)
Backed out changeset dd266975e407 (bug 1083101)

CLOSED TREE
2015-09-01 11:35:02 -04:00

316 lines
7.5 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SourceSurfaceD2DTarget.h"
#include "Logging.h"
#include "DrawTargetD2D.h"
#include "Tools.h"
#include <algorithm>
namespace mozilla {
namespace gfx {
SourceSurfaceD2DTarget::SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget,
ID3D10Texture2D* aTexture,
SurfaceFormat aFormat)
: mDrawTarget(aDrawTarget)
, mTexture(aTexture)
, mFormat(aFormat)
, mOwnsCopy(false)
{
}
SourceSurfaceD2DTarget::~SourceSurfaceD2DTarget()
{
// We don't need to do anything special here to notify our mDrawTarget. It must
// already have cleared its mSnapshot field, otherwise this object would
// be kept alive.
if (mOwnsCopy) {
IntSize size = GetSize();
DrawTargetD2D::mVRAMUsageSS -= size.width * size.height * BytesPerPixel(mFormat);
}
}
IntSize
SourceSurfaceD2DTarget::GetSize() const
{
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
return IntSize(desc.Width, desc.Height);
}
SurfaceFormat
SourceSurfaceD2DTarget::GetFormat() const
{
return mFormat;
}
already_AddRefed<DataSourceSurface>
SourceSurfaceD2DTarget::GetDataSurface()
{
RefPtr<DataSourceSurfaceD2DTarget> dataSurf =
new DataSourceSurfaceD2DTarget(mFormat);
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
desc.Usage = D3D10_USAGE_STAGING;
desc.BindFlags = 0;
desc.MiscFlags = 0;
HRESULT hr = Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, byRef(dataSurf->mTexture));
if (FAILED(hr)) {
gfxDebug() << "Failed to create staging texture for SourceSurface. Code: " << hexa(hr);
return nullptr;
}
Factory::GetDirect3D10Device()->CopyResource(dataSurf->mTexture, mTexture);
return dataSurf.forget();
}
void*
SourceSurfaceD2DTarget::GetNativeSurface(NativeSurfaceType aType)
{
if (aType == NativeSurfaceType::D3D10_TEXTURE) {
return static_cast<void*>(mTexture.get());
}
return nullptr;
}
ID3D10ShaderResourceView*
SourceSurfaceD2DTarget::GetSRView()
{
if (mSRView) {
return mSRView;
}
HRESULT hr = Factory::GetDirect3D10Device()->CreateShaderResourceView(mTexture, nullptr, byRef(mSRView));
if (FAILED(hr)) {
gfxWarning() << "Failed to create ShaderResourceView. Code: " << hexa(hr);
}
return mSRView;
}
void
SourceSurfaceD2DTarget::DrawTargetWillChange()
{
RefPtr<ID3D10Texture2D> oldTexture = mTexture;
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
// Our original texture might implement the keyed mutex flag. We shouldn't
// need that here. We actually specifically don't want it since we don't lock
// our texture for usage!
desc.MiscFlags = 0;
// Get a copy of the surface data so the content at snapshot time was saved.
Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, byRef(mTexture));
Factory::GetDirect3D10Device()->CopyResource(mTexture, oldTexture);
mBitmap = nullptr;
DrawTargetD2D::mVRAMUsageSS += desc.Width * desc.Height * BytesPerPixel(mFormat);
mOwnsCopy = true;
// We now no longer depend on the source surface content remaining the same.
MarkIndependent();
}
ID2D1Bitmap*
SourceSurfaceD2DTarget::GetBitmap(ID2D1RenderTarget *aRT)
{
if (mBitmap) {
return mBitmap;
}
HRESULT hr;
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
IntSize size(desc.Width, desc.Height);
RefPtr<IDXGISurface> surf;
hr = mTexture->QueryInterface((IDXGISurface**)byRef(surf));
if (FAILED(hr)) {
gfxWarning() << "Failed to query interface texture to DXGISurface. Code: " << hexa(hr);
return nullptr;
}
D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(mFormat));
hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
if (FAILED(hr)) {
// This seems to happen for SurfaceFormat::A8 sometimes...
hr = aRT->CreateBitmap(D2D1::SizeU(desc.Width, desc.Height),
D2D1::BitmapProperties(D2DPixelFormat(mFormat)),
byRef(mBitmap));
if (FAILED(hr)) {
gfxWarning() << "Failed in CreateBitmap. Code: " << hexa(hr);
return nullptr;
}
RefPtr<ID2D1RenderTarget> rt;
if (mDrawTarget) {
rt = mDrawTarget->mRT;
}
if (!rt) {
// Okay, we already separated from our drawtarget. And we're an A8
// surface the only way we can get to a bitmap is by creating a
// a rendertarget and from there copying to a bitmap! Terrible!
RefPtr<IDXGISurface> surface;
hr = mTexture->QueryInterface((IDXGISurface**)byRef(surface));
if (FAILED(hr)) {
gfxWarning() << "Failed to QI texture to surface.";
return nullptr;
}
D2D1_RENDER_TARGET_PROPERTIES props =
D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2DPixelFormat(mFormat));
hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(surface, props, byRef(rt));
if (FAILED(hr)) {
gfxWarning() << "Failed to create D2D render target for texture.";
return nullptr;
}
}
mBitmap->CopyFromRenderTarget(nullptr, rt, nullptr);
return mBitmap;
}
return mBitmap;
}
void
SourceSurfaceD2DTarget::MarkIndependent()
{
if (mDrawTarget) {
MOZ_ASSERT(mDrawTarget->mSnapshot == this);
mDrawTarget->mSnapshot = nullptr;
mDrawTarget = nullptr;
}
}
DataSourceSurfaceD2DTarget::DataSourceSurfaceD2DTarget(SurfaceFormat aFormat)
: mFormat(aFormat)
, mMapped(false)
{
}
DataSourceSurfaceD2DTarget::~DataSourceSurfaceD2DTarget()
{
if (mMapped) {
mTexture->Unmap(0);
}
}
IntSize
DataSourceSurfaceD2DTarget::GetSize() const
{
D3D10_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
return IntSize(desc.Width, desc.Height);
}
SurfaceFormat
DataSourceSurfaceD2DTarget::GetFormat() const
{
return mFormat;
}
uint8_t*
DataSourceSurfaceD2DTarget::GetData()
{
EnsureMapped();
return (unsigned char*)mMap.pData;
}
int32_t
DataSourceSurfaceD2DTarget::Stride()
{
EnsureMapped();
return mMap.RowPitch;
}
bool
DataSourceSurfaceD2DTarget::Map(MapType aMapType, MappedSurface *aMappedSurface)
{
// DataSourceSurfaces used with the new Map API should not be used with GetData!!
MOZ_ASSERT(!mMapped);
MOZ_ASSERT(!mIsMapped);
if (!mTexture) {
return false;
}
D3D10_MAP mapType;
if (aMapType == MapType::READ) {
mapType = D3D10_MAP_READ;
} else if (aMapType == MapType::WRITE) {
mapType = D3D10_MAP_WRITE;
} else {
mapType = D3D10_MAP_READ_WRITE;
}
D3D10_MAPPED_TEXTURE2D map;
HRESULT hr = mTexture->Map(0, mapType, 0, &map);
if (FAILED(hr)) {
gfxWarning() << "Texture map failed with code: " << hexa(hr);
return false;
}
aMappedSurface->mData = (uint8_t*)map.pData;
aMappedSurface->mStride = map.RowPitch;
mIsMapped = !!aMappedSurface->mData;
return mIsMapped;
}
void
DataSourceSurfaceD2DTarget::Unmap()
{
MOZ_ASSERT(mIsMapped);
mIsMapped = false;
mTexture->Unmap(0);
}
void
DataSourceSurfaceD2DTarget::EnsureMapped()
{
// Do not use GetData() after having used Map!
MOZ_ASSERT(!mIsMapped);
if (!mMapped) {
HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mMap);
if (FAILED(hr)) {
gfxWarning() << "Failed to map texture to memory. Code: " << hexa(hr);
return;
}
mMapped = true;
}
}
}
}