mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-30 13:45:27 +00:00
606e8823ff
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
316 lines
7.5 KiB
C++
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|