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
318 lines
7.8 KiB
C++
318 lines
7.8 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 "SourceSurfaceD2D.h"
|
|
#include "DrawTargetD2D.h"
|
|
#include "Logging.h"
|
|
#include "Tools.h"
|
|
|
|
namespace mozilla {
|
|
namespace gfx {
|
|
|
|
SourceSurfaceD2D::SourceSurfaceD2D()
|
|
{
|
|
}
|
|
|
|
SourceSurfaceD2D::~SourceSurfaceD2D()
|
|
{
|
|
if (mBitmap) {
|
|
DrawTargetD2D::mVRAMUsageSS -= GetByteSize();
|
|
}
|
|
}
|
|
|
|
IntSize
|
|
SourceSurfaceD2D::GetSize() const
|
|
{
|
|
return mSize;
|
|
}
|
|
|
|
SurfaceFormat
|
|
SourceSurfaceD2D::GetFormat() const
|
|
{
|
|
return mFormat;
|
|
}
|
|
|
|
bool
|
|
SourceSurfaceD2D::IsValid() const
|
|
{
|
|
return mDevice == Factory::GetDirect3D10Device();
|
|
}
|
|
|
|
already_AddRefed<DataSourceSurface>
|
|
SourceSurfaceD2D::GetDataSurface()
|
|
{
|
|
RefPtr<DataSourceSurfaceD2D> result = new DataSourceSurfaceD2D(this);
|
|
if (result->IsValid()) {
|
|
return result.forget();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool
|
|
SourceSurfaceD2D::InitFromData(unsigned char *aData,
|
|
const IntSize &aSize,
|
|
int32_t aStride,
|
|
SurfaceFormat aFormat,
|
|
ID2D1RenderTarget *aRT)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mFormat = aFormat;
|
|
mSize = aSize;
|
|
|
|
if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
|
|
(uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
|
|
gfxDebug() << "Bitmap does not fit in texture.";
|
|
return false;
|
|
}
|
|
|
|
D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
|
|
hr = aRT->CreateBitmap(D2DIntSize(aSize), props, byRef(mBitmap));
|
|
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hexa(hr);
|
|
return false;
|
|
}
|
|
|
|
hr = mBitmap->CopyFromMemory(nullptr, aData, aStride);
|
|
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to copy data to D2D bitmap. Code: " << hexa(hr);
|
|
return false;
|
|
}
|
|
|
|
DrawTargetD2D::mVRAMUsageSS += GetByteSize();
|
|
mDevice = Factory::GetDirect3D10Device();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SourceSurfaceD2D::InitFromTexture(ID3D10Texture2D *aTexture,
|
|
SurfaceFormat aFormat,
|
|
ID2D1RenderTarget *aRT)
|
|
{
|
|
HRESULT hr;
|
|
|
|
RefPtr<IDXGISurface> surf;
|
|
|
|
hr = aTexture->QueryInterface((IDXGISurface**)&surf);
|
|
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to QI texture to surface. Code: " << hexa(hr);
|
|
return false;
|
|
}
|
|
|
|
D3D10_TEXTURE2D_DESC desc;
|
|
aTexture->GetDesc(&desc);
|
|
|
|
mSize = IntSize(desc.Width, desc.Height);
|
|
mFormat = aFormat;
|
|
|
|
D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
|
|
hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
|
|
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to create SharedBitmap. Code: " << hexa(hr);
|
|
return false;
|
|
}
|
|
|
|
aTexture->GetDevice(byRef(mDevice));
|
|
DrawTargetD2D::mVRAMUsageSS += GetByteSize();
|
|
|
|
return true;
|
|
}
|
|
|
|
uint32_t
|
|
SourceSurfaceD2D::GetByteSize() const
|
|
{
|
|
return mSize.width * mSize.height * BytesPerPixel(mFormat);
|
|
}
|
|
|
|
DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface)
|
|
: mTexture(nullptr)
|
|
, mFormat(aSourceSurface->mFormat)
|
|
, mSize(aSourceSurface->mSize)
|
|
, mMapped(false)
|
|
{
|
|
// We allocate ourselves a regular D3D surface (sourceTexture) and paint the
|
|
// D2D bitmap into it via a DXGI render target. Then we need to copy
|
|
// sourceTexture into a staging texture (mTexture), which we will lazily map
|
|
// to get the data.
|
|
|
|
CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height);
|
|
desc.MipLevels = 1;
|
|
desc.Usage = D3D10_USAGE_DEFAULT;
|
|
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
|
RefPtr<ID3D10Texture2D> sourceTexture;
|
|
HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr,
|
|
byRef(sourceTexture));
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to create texture. Code: " << hexa(hr);
|
|
return;
|
|
}
|
|
|
|
RefPtr<IDXGISurface> dxgiSurface;
|
|
hr = sourceTexture->QueryInterface((IDXGISurface**)byRef(dxgiSurface));
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to create DXGI surface. Code: " << hexa(hr);
|
|
return;
|
|
}
|
|
|
|
D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
|
|
D2D1_RENDER_TARGET_TYPE_DEFAULT,
|
|
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
|
|
|
|
RefPtr<ID2D1RenderTarget> renderTarget;
|
|
hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
|
|
&rtProps,
|
|
byRef(renderTarget));
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to create render target. Code: " << hexa(hr);
|
|
return;
|
|
}
|
|
|
|
renderTarget->BeginDraw();
|
|
renderTarget->Clear(D2D1::ColorF(0, 0.0f));
|
|
if (aSourceSurface->GetFormat() != SurfaceFormat::A8) {
|
|
renderTarget->DrawBitmap(aSourceSurface->mBitmap,
|
|
D2D1::RectF(0, 0,
|
|
Float(mSize.width),
|
|
Float(mSize.height)));
|
|
} else {
|
|
RefPtr<ID2D1SolidColorBrush> brush;
|
|
renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), byRef(brush));
|
|
renderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
|
|
renderTarget->FillOpacityMask(aSourceSurface->mBitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
|
|
}
|
|
hr = renderTarget->EndDraw();
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to draw bitmap. Code: " << hexa(hr);
|
|
return;
|
|
}
|
|
|
|
desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE;
|
|
desc.Usage = D3D10_USAGE_STAGING;
|
|
desc.BindFlags = 0;
|
|
hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture));
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to create staging texture. Code: " << hexa(hr);
|
|
mTexture = nullptr;
|
|
return;
|
|
}
|
|
|
|
aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture);
|
|
}
|
|
|
|
DataSourceSurfaceD2D::~DataSourceSurfaceD2D()
|
|
{
|
|
if (mMapped) {
|
|
mTexture->Unmap(0);
|
|
}
|
|
}
|
|
|
|
unsigned char*
|
|
DataSourceSurfaceD2D::GetData()
|
|
{
|
|
EnsureMappedTexture();
|
|
if (!mMapped) {
|
|
return nullptr;
|
|
}
|
|
|
|
return reinterpret_cast<unsigned char*>(mData.pData);
|
|
}
|
|
|
|
int32_t
|
|
DataSourceSurfaceD2D::Stride()
|
|
{
|
|
EnsureMappedTexture();
|
|
if (!mMapped) {
|
|
return 0;
|
|
}
|
|
|
|
return mData.RowPitch;
|
|
}
|
|
|
|
IntSize
|
|
DataSourceSurfaceD2D::GetSize() const
|
|
{
|
|
return mSize;
|
|
}
|
|
|
|
SurfaceFormat
|
|
DataSourceSurfaceD2D::GetFormat() const
|
|
{
|
|
return mFormat;
|
|
}
|
|
|
|
bool
|
|
DataSourceSurfaceD2D::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
|
|
DataSourceSurfaceD2D::Unmap()
|
|
{
|
|
MOZ_ASSERT(mIsMapped);
|
|
|
|
mIsMapped = false;
|
|
mTexture->Unmap(0);
|
|
}
|
|
|
|
void
|
|
DataSourceSurfaceD2D::EnsureMappedTexture()
|
|
{
|
|
// Do not use GetData() after having used Map!
|
|
MOZ_ASSERT(!mIsMapped);
|
|
|
|
if (mMapped ||
|
|
!mTexture) {
|
|
return;
|
|
}
|
|
|
|
HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mData);
|
|
if (FAILED(hr)) {
|
|
gfxWarning() << "Failed to map texture. Code: " << hexa(hr);
|
|
mTexture = nullptr;
|
|
} else {
|
|
mMapped = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|