From 54dad93d7475d7235c9364b623520835a32fcae7 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Fri, 12 Feb 2016 02:11:50 +0100 Subject: [PATCH] Bug 1247775 - Part 3: Remove Moz2D code to support Direct2D 1.0. r=dvander MozReview-Commit-ID: KBZSqIdx0OC --HG-- extra : rebase_source : 632fb5208a702f79fa5c648698f73bc9b0bf8992 --- gfx/2d/2D.h | 11 - gfx/2d/DrawTargetD2D.cpp | 2831 --------------------------- gfx/2d/DrawTargetD2D.h | 290 --- gfx/2d/DrawTargetD2D1.cpp | 74 +- gfx/2d/Factory.cpp | 99 +- gfx/2d/FilterNodeD2D1.cpp | 5 - gfx/2d/HelpersD2D.h | 3 +- gfx/2d/NativeFontResourceDWrite.cpp | 6 +- gfx/2d/PathD2D.cpp | 4 +- gfx/2d/ScaledFontDWrite.cpp | 4 +- gfx/2d/SourceSurfaceD2D.cpp | 317 --- gfx/2d/SourceSurfaceD2D.h | 90 - gfx/2d/SourceSurfaceD2DTarget.cpp | 325 --- gfx/2d/SourceSurfaceD2DTarget.h | 90 - gfx/2d/Types.h | 2 +- gfx/2d/moz.build | 3 - 16 files changed, 78 insertions(+), 4076 deletions(-) delete mode 100644 gfx/2d/DrawTargetD2D.cpp delete mode 100644 gfx/2d/DrawTargetD2D.h delete mode 100644 gfx/2d/SourceSurfaceD2D.cpp delete mode 100644 gfx/2d/SourceSurfaceD2D.h delete mode 100644 gfx/2d/SourceSurfaceD2DTarget.cpp delete mode 100644 gfx/2d/SourceSurfaceD2DTarget.h diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 6913ce9b8494..f233e4346f9d 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -36,8 +36,6 @@ typedef _cairo_surface cairo_surface_t; struct _cairo_scaled_font; typedef _cairo_scaled_font cairo_scaled_font_t; -struct ID3D10Device1; -struct ID3D10Texture2D; struct ID3D11Texture2D; struct ID3D11Device; struct ID2D1Device; @@ -1364,14 +1362,6 @@ public: #endif #ifdef WIN32 - static already_AddRefed CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); - static already_AddRefed - CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA, - ID3D10Texture2D *aTextureB, - SurfaceFormat aFormat); - - static void SetDirect3D10Device(ID3D10Device1 *aDevice); - static ID3D10Device1 *GetDirect3D10Device(); static already_AddRefed CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat); static void SetDirect3D11Device(ID3D11Device *aDevice); @@ -1394,7 +1384,6 @@ public: private: static ID2D1Device *mD2D1Device; - static ID3D10Device1 *mD3D10Device; static ID3D11Device *mD3D11Device; #endif diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp deleted file mode 100644 index f1e2731090ac..000000000000 --- a/gfx/2d/DrawTargetD2D.cpp +++ /dev/null @@ -1,2831 +0,0 @@ -/* -*- 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 -#include "DrawTargetD2D.h" -#include "SourceSurfaceD2D.h" -#include "SourceSurfaceD2D1.h" -#include "SourceSurfaceD2DTarget.h" -#include "ShadersD2D.h" -#include "PathD2D.h" -#include "GradientStopsD2D.h" -#include "ScaledFontDWrite.h" -#include "ImageScaling.h" -#include "Logging.h" -#include "Tools.h" -#include -#include "FilterNodeSoftware.h" - -#include "FilterNodeD2D1.h" -#include "ExtendInputEffectD2D1.h" - -#include -#include - -// decltype is not usable for overloaded functions. -typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)( - D2D1_FACTORY_TYPE factoryType, - REFIID iid, - CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, - void **factory -); - -using namespace std; - -namespace mozilla { -namespace gfx { - -struct Vertex { - float x; - float y; -}; - -ID2D1Factory *DrawTargetD2D::mFactory; -IDWriteFactory *DrawTargetD2D::mDWriteFactory; -uint64_t DrawTargetD2D::mVRAMUsageDT; -uint64_t DrawTargetD2D::mVRAMUsageSS; - -// Helper class to restore surface contents that was clipped out but may have -// been altered by a drawing call. -class AutoSaveRestoreClippedOut -{ -public: - AutoSaveRestoreClippedOut(DrawTargetD2D *aDT) - : mDT(aDT) - {} - - void Save() { - if (!mDT->mPushedClips.size()) { - return; - } - - mDT->Flush(); - - RefPtr tmpTexture; - IntSize size = mDT->mSize; - SurfaceFormat format = mDT->mFormat; - - CD3D10_TEXTURE2D_DESC desc(DXGIFormat(format), size.width, size.height, - 1, 1); - desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - - HRESULT hr = mDT->mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(tmpTexture)); - if (FAILED(hr)) { - gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(size))) << "[D2D] 1 CreateTexture2D failure " << size << " Code: " << hexa(hr) << " format " << (int)format; - return; - } - mDT->mDevice->CopyResource(tmpTexture, mDT->mTexture); - - D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(format)); - - RefPtr surf; - - tmpTexture->QueryInterface((IDXGISurface**)getter_AddRefs(surf)); - - hr = mDT->mRT->CreateSharedBitmap(IID_IDXGISurface, surf, - &props, getter_AddRefs(mOldSurfBitmap)); - - if (FAILED(hr)) { - gfxCriticalError() << "[D2D] CreateSharedBitmap failure " << size << " Code: " << hexa(hr); - return; - } - - IntRect clipBounds; - mClippedArea = mDT->GetClippedGeometry(&clipBounds); - - if (!clipBounds.IsEqualEdges(IntRect(IntPoint(0, 0), mDT->mSize))) { - // We still need to take into account clipBounds if it contains additional - // clipping information. - RefPtr rectGeom; - factory()->CreateRectangleGeometry(D2D1::Rect(Float(clipBounds.x), - Float(clipBounds.y), - Float(clipBounds.XMost()), - Float(clipBounds.YMost())), - getter_AddRefs(rectGeom)); - - mClippedArea = IntersectGeometry(mClippedArea, rectGeom); - } - } - - ID2D1Factory *factory() { return mDT->factory(); } - - ~AutoSaveRestoreClippedOut() - { - if (!mOldSurfBitmap) { - return; - } - - ID2D1RenderTarget *rt = mDT->mRT; - - // Write the area that was clipped out back to the surface. This all - // happens in device space. - rt->SetTransform(D2D1::IdentityMatrix()); - mDT->mTransformDirty = true; - - RefPtr rectGeom; - factory()->CreateRectangleGeometry( - D2D1::RectF(0, 0, float(mDT->mSize.width), float(mDT->mSize.height)), - getter_AddRefs(rectGeom)); - - RefPtr invClippedArea; - factory()->CreatePathGeometry(getter_AddRefs(invClippedArea)); - RefPtr sink; - invClippedArea->Open(getter_AddRefs(sink)); - - rectGeom->CombineWithGeometry(mClippedArea, D2D1_COMBINE_MODE_EXCLUDE, nullptr, sink); - sink->Close(); - - RefPtr brush; - HRESULT hr = rt->CreateBitmapBrush(mOldSurfBitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(), getter_AddRefs(brush)); - if (FAILED(hr)) { - gfxCriticalNote << "[D2D] CreateBitmapBrush failure " << hexa(hr); - return; - } - - rt->FillGeometry(invClippedArea, brush); - } - -private: - - DrawTargetD2D *mDT; - - // If we have an operator unbound by the source, this will contain a bitmap - // with the old dest surface data. - RefPtr mOldSurfBitmap; - // This contains the area drawing is clipped to. - RefPtr mClippedArea; -}; - -ID2D1Factory *D2DFactory() -{ - return DrawTargetD2D::factory(); -} - -DrawTargetD2D::DrawTargetD2D() - : mCurrentCachedLayer(0) - , mClipsArePushed(false) - , mPrivateData(nullptr) -{ -} - -DrawTargetD2D::~DrawTargetD2D() -{ - if (mRT) { - PopAllClips(); - - mRT->EndDraw(); - - mVRAMUsageDT -= GetByteSize(); - } - if (mTempRT) { - mTempRT->EndDraw(); - - mVRAMUsageDT -= GetByteSize(); - } - - if (mSnapshot) { - // We may hold the only reference. MarkIndependent will clear mSnapshot; - // keep the snapshot object alive so it doesn't get destroyed while - // MarkIndependent is running. - RefPtr deathGrip = mSnapshot; - // mSnapshot can be treated as independent of this DrawTarget since we know - // this DrawTarget won't change again. - deathGrip->MarkIndependent(); - // mSnapshot will be cleared now. - } - - for (int i = 0; i < kLayerCacheSize; i++) { - if (mCachedLayers[i]) { - mCachedLayers[i] = nullptr; - mVRAMUsageDT -= GetByteSize(); - } - } - - // Targets depending on us can break that dependency, since we're obviously not going to - // be modified in the future. - for (TargetSet::iterator iter = mDependentTargets.begin(); - iter != mDependentTargets.end(); iter++) { - (*iter)->mDependingOnTargets.erase(this); - } - // Our dependencies on other targets no longer matter. - for (TargetSet::iterator iter = mDependingOnTargets.begin(); - iter != mDependingOnTargets.end(); iter++) { - (*iter)->mDependentTargets.erase(this); - } -} - -/* - * DrawTarget Implementation - */ -already_AddRefed -DrawTargetD2D::Snapshot() -{ - if (!mSnapshot) { - mSnapshot = new SourceSurfaceD2DTarget(this, mTexture, mFormat); - Flush(); - } - - RefPtr snapshot(mSnapshot); - return snapshot.forget(); -} - -void -DrawTargetD2D::Flush() -{ - PopAllClips(); - - HRESULT hr = mRT->Flush(); - - if (FAILED(hr)) { - gfxWarning() << "Error reported when trying to flush D2D rendertarget. Code: " << hexa(hr); - } - - // We no longer depend on any target. - for (TargetSet::iterator iter = mDependingOnTargets.begin(); - iter != mDependingOnTargets.end(); iter++) { - (*iter)->mDependentTargets.erase(this); - } - mDependingOnTargets.clear(); -} - -void -DrawTargetD2D::AddDependencyOnSource(SourceSurfaceD2DTarget* aSource) -{ - if (aSource->mDrawTarget && !mDependingOnTargets.count(aSource->mDrawTarget)) { - aSource->mDrawTarget->mDependentTargets.insert(this); - mDependingOnTargets.insert(aSource->mDrawTarget); - } -} - -already_AddRefed -DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface, - Rect &aSource) -{ - RefPtr bitmap; - - switch (aSurface->GetType()) { - - case SurfaceType::D2D1_BITMAP: - { - SourceSurfaceD2D *srcSurf = static_cast(aSurface); - bitmap = srcSurf->GetBitmap(); - } - break; - case SurfaceType::D2D1_DRAWTARGET: - { - SourceSurfaceD2DTarget *srcSurf = static_cast(aSurface); - bitmap = srcSurf->GetBitmap(mRT); - AddDependencyOnSource(srcSurf); - } - break; - default: - { - RefPtr srcSurf = aSurface->GetDataSurface(); - - if (!srcSurf) { - gfxDebug() << "Not able to deal with non-data source surface."; - return nullptr; - } - - // We need to include any pixels that are overlapped by aSource - Rect sourceRect(aSource); - sourceRect.RoundOut(); - - if (sourceRect.IsEmpty()) { - gfxDebug() << "Bitmap source is empty. DrawBitmap will silently fail."; - return nullptr; - } - - if (sourceRect.width > mRT->GetMaximumBitmapSize() || - sourceRect.height > mRT->GetMaximumBitmapSize()) { - gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail."; - // Don't know how to deal with this yet. - return nullptr; - } - - HRESULT hr; - { - DataSourceSurface::ScopedMap srcMap(srcSurf, DataSourceSurface::READ); - if (MOZ2D_WARN_IF(!srcMap.IsMapped())) { - return nullptr; - } - - int stride = srcMap.GetStride(); - unsigned char *data = srcMap.GetData() + - (uint32_t)sourceRect.y * stride + - (uint32_t)sourceRect.x * BytesPerPixel(srcSurf->GetFormat()); - - D2D1_BITMAP_PROPERTIES props = - D2D1::BitmapProperties(D2DPixelFormat(srcSurf->GetFormat())); - hr = mRT->CreateBitmap(D2D1::SizeU(UINT32(sourceRect.width), UINT32(sourceRect.height)), data, stride, props, getter_AddRefs(bitmap)); - } - if (FAILED(hr)) { - IntSize size(sourceRect.width, sourceRect.height); - gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(size))) << "[D2D] 1CreateBitmap failure " << size << " Code: " << hexa(hr) << " format " << (int)srcSurf->GetFormat(); - return nullptr; - } - - // subtract the integer part leaving the fractional part - aSource.x -= (uint32_t)aSource.x; - aSource.y -= (uint32_t)aSource.y; - } - break; - } - - return bitmap.forget(); -} - -already_AddRefed -DrawTargetD2D::GetImageForSurface(SourceSurface *aSurface) -{ - RefPtr image; - - Rect r(Point(), Size(aSurface->GetSize())); - image = GetBitmapForSurface(aSurface, r); - - return image.forget(); -} - -void -DrawTargetD2D::DrawSurface(SourceSurface *aSurface, - const Rect &aDest, - const Rect &aSource, - const DrawSurfaceOptions &aSurfOptions, - const DrawOptions &aOptions) -{ - RefPtr bitmap; - - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color())); - - PrepareForDrawing(rt); - - rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode)); - - Rect srcRect = aSource; - - bitmap = GetBitmapForSurface(aSurface, srcRect); - if (!bitmap) { - return; - } - - rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect)); - - FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), aDest); -} - -void -DrawTargetD2D::DrawFilter(FilterNode *aNode, - const Rect &aSourceRect, - const Point &aDestPoint, - const DrawOptions &aOptions) -{ - RefPtr dc; - HRESULT hr; - - hr = mRT->QueryInterface((ID2D1DeviceContext**)getter_AddRefs(dc)); - - if (SUCCEEDED(hr) && aNode->GetBackendType() == FILTER_BACKEND_DIRECT2D1_1) { - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color())); - - PrepareForDrawing(rt); - - rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode)); - hr = rt->QueryInterface((ID2D1DeviceContext**)getter_AddRefs(dc)); - - if (SUCCEEDED(hr)) { - FilterNodeD2D1* node = static_cast(aNode); - node->WillDraw(this); - - dc->DrawImage(node->OutputEffect(), D2DPoint(aDestPoint), D2DRect(aSourceRect)); - - Rect destRect = aSourceRect; - destRect.MoveBy(aDestPoint); - FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), destRect); - return; - } - } - - if (aNode->GetBackendType() != FILTER_BACKEND_SOFTWARE) { - gfxWarning() << "Invalid filter backend passed to DrawTargetD2D!"; - return; - } - - FilterNodeSoftware* filter = static_cast(aNode); - filter->Draw(this, aSourceRect, aDestPoint, aOptions); -} - -void -DrawTargetD2D::MaskSurface(const Pattern &aSource, - SourceSurface *aMask, - Point aOffset, - const DrawOptions &aOptions) -{ - RefPtr bitmap; - - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color())); - - PrepareForDrawing(rt); - - // FillOpacityMask only works if the antialias mode is MODE_ALIASED - rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); - - IntSize size = aMask->GetSize(); - Rect maskRect = Rect(0.f, 0.f, size.width, size.height); - bitmap = GetBitmapForSurface(aMask, maskRect); - if (!bitmap) { - return; - } - - Rect dest = Rect(aOffset.x, aOffset.y, size.width, size.height); - RefPtr brush = CreateBrushForPattern(aSource, aOptions.mAlpha); - rt->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2DRect(dest), D2DRect(maskRect)); - - FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), dest); -} - -void -DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, - const Point &aDest, - const Color &aColor, - const Point &aOffset, - Float aSigma, - CompositionOp aOperator) -{ - RefPtr srView = nullptr; - if (aSurface->GetType() != SurfaceType::D2D1_DRAWTARGET) { - return; - } - - SetScissorToRect(nullptr); - - // XXX - This function is way too long, it should be split up soon to make - // it more graspable! - - Flush(); - - AutoSaveRestoreClippedOut restoreClippedOut(this); - - if (!IsOperatorBoundByMask(aOperator)) { - restoreClippedOut.Save(); - } - - srView = static_cast(aSurface)->GetSRView(); - if (!srView) { - return; - } - - EnsureViews(); - - if (!mTempRTView) { - // This view is only needed in this path. - HRESULT hr = mDevice->CreateRenderTargetView(mTempTexture, nullptr, getter_AddRefs(mTempRTView)); - - if (FAILED(hr)) { - gfxWarning() << "Failure to create RenderTargetView. Code: " << hexa(hr); - return; - } - } - - - RefPtr destRTView = mRTView; - RefPtr destTexture; - HRESULT hr; - - RefPtr maskTexture; - RefPtr maskSRView; - IntRect clipBounds; - if (mPushedClips.size()) { - EnsureClipMaskTexture(&clipBounds); - - mDevice->CreateShaderResourceView(mCurrentClipMaskTexture, nullptr, getter_AddRefs(maskSRView)); - } - - IntSize srcSurfSize; - ID3D10RenderTargetView *rtViews; - D3D10_VIEWPORT viewport; - - UINT stride = sizeof(Vertex); - UINT offset = 0; - ID3D10Buffer *buff = mPrivateData->mVB; - - mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - mDevice->IASetVertexBuffers(0, 1, &buff, &stride, &offset); - mDevice->IASetInputLayout(mPrivateData->mInputLayout); - - mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(-1.0f, 1.0f, 2.0f, -2.0f)); - mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); - - // If we create a downsampled source surface we need to correct aOffset for that. - Point correctedOffset = aOffset + aDest; - - // The 'practical' scaling factors. - Float dsFactorX = 1.0f; - Float dsFactorY = 1.0f; - - if (aSigma > 1.7f) { - // In this case 9 samples of our original will not cover it. Generate the - // mip levels for the original and create a downsampled version from - // them. We generate a version downsampled so that a kernel for a sigma - // of 1.7 will produce the right results. - float blurWeights[9] = { 0.234671f, 0.197389f, 0.197389f, 0.117465f, 0.117465f, 0.049456f, 0.049456f, 0.014732f, 0.014732f }; - mPrivateData->mEffect->GetVariableByName("BlurWeights")->SetRawValue(blurWeights, 0, sizeof(blurWeights)); - - CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, - aSurface->GetSize().width, - aSurface->GetSize().height); - desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - desc.MiscFlags = D3D10_RESOURCE_MISC_GENERATE_MIPS; - - RefPtr mipTexture; - hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mipTexture)); - - if (FAILED(hr)) { - gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSurface->GetSize()))) << "[D2D] 2 CreateTexture2D failure " << aSurface->GetSize() << " Code: " << hexa(hr); - return; - } - - IntSize dsSize = IntSize(int32_t(aSurface->GetSize().width * (1.7f / aSigma)), - int32_t(aSurface->GetSize().height * (1.7f / aSigma))); - - if (dsSize.width < 1) { - dsSize.width = 1; - } - if (dsSize.height < 1) { - dsSize.height = 1; - } - - dsFactorX = dsSize.width / Float(aSurface->GetSize().width); - dsFactorY = dsSize.height / Float(aSurface->GetSize().height); - correctedOffset.x *= dsFactorX; - correctedOffset.y *= dsFactorY; - - desc = CD3D10_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, - dsSize.width, - dsSize.height, 1, 1); - desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - RefPtr tmpDSTexture; - hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(tmpDSTexture)); - - if (FAILED(hr)) { - gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(dsSize))) << "[D2D] 3 CreateTexture2D failure " << dsSize << " Code: " << hexa(hr); - return; - } - - D3D10_BOX box; - box.left = box.top = box.front = 0; - box.back = 1; - box.right = aSurface->GetSize().width; - box.bottom = aSurface->GetSize().height; - mDevice->CopySubresourceRegion(mipTexture, 0, 0, 0, 0, static_cast(aSurface)->mTexture, 0, &box); - - mDevice->CreateShaderResourceView(mipTexture, nullptr, getter_AddRefs(srView)); - mDevice->GenerateMips(srView); - - RefPtr dsRTView; - RefPtr dsSRView; - mDevice->CreateRenderTargetView(tmpDSTexture, nullptr, getter_AddRefs(dsRTView)); - mDevice->CreateShaderResourceView(tmpDSTexture, nullptr, getter_AddRefs(dsSRView)); - - // We're not guaranteed the texture we created will be empty, we've - // seen old content at least on NVidia drivers. - float color[4] = { 0, 0, 0, 0 }; - mDevice->ClearRenderTargetView(dsRTView, color); - - rtViews = dsRTView; - mDevice->OMSetRenderTargets(1, &rtViews, nullptr); - - viewport.MaxDepth = 1; - viewport.MinDepth = 0; - viewport.Height = dsSize.height; - viewport.Width = dsSize.width; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - - mDevice->RSSetViewports(1, &viewport); - mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView); - mPrivateData->mEffect->GetTechniqueByName("SampleTexture")-> - GetPassByIndex(0)->Apply(0); - - mDevice->OMSetBlendState(GetBlendStateForOperator(CompositionOp::OP_OVER), nullptr, 0xffffffff); - - mDevice->Draw(4, 0); - - srcSurfSize = dsSize; - - srView = dsSRView; - } else { - // In this case generate a kernel to draw the blur directly to the temp - // surf in one direction and to final in the other. - float blurWeights[9]; - - float normalizeFactor = 1.0f; - if (aSigma != 0) { - normalizeFactor = 1.0f / Float(sqrt(2 * M_PI * pow(aSigma, 2))); - } - - blurWeights[0] = normalizeFactor; - - // XXX - We should actually optimize for Sigma = 0 here. We could use a - // much simpler shader and save a lot of texture lookups. - for (int i = 1; i < 9; i += 2) { - if (aSigma != 0) { - blurWeights[i] = blurWeights[i + 1] = normalizeFactor * - exp(-pow(float((i + 1) / 2), 2) / (2 * pow(aSigma, 2))); - } else { - blurWeights[i] = blurWeights[i + 1] = 0; - } - } - - mPrivateData->mEffect->GetVariableByName("BlurWeights")->SetRawValue(blurWeights, 0, sizeof(blurWeights)); - - viewport.MaxDepth = 1; - viewport.MinDepth = 0; - viewport.Height = aSurface->GetSize().height; - viewport.Width = aSurface->GetSize().width; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - - mDevice->RSSetViewports(1, &viewport); - - srcSurfSize = aSurface->GetSize(); - } - - // We may need to draw to a different intermediate surface if our temp - // texture isn't big enough. - bool needBiggerTemp = srcSurfSize.width > mSize.width || - srcSurfSize.height > mSize.height; - - RefPtr tmpRTView; - RefPtr tmpSRView; - RefPtr tmpTexture; - - IntSize tmpSurfSize = mSize; - - if (!needBiggerTemp) { - tmpRTView = mTempRTView; - tmpSRView = mSRView; - - // There could still be content here! - float color[4] = { 0, 0, 0, 0 }; - mDevice->ClearRenderTargetView(tmpRTView, color); - } else { - CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, - srcSurfSize.width, - srcSurfSize.height, - 1, 1); - desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - - mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(tmpTexture)); - mDevice->CreateRenderTargetView(tmpTexture, nullptr, getter_AddRefs(tmpRTView)); - mDevice->CreateShaderResourceView(tmpTexture, nullptr, getter_AddRefs(tmpSRView)); - - tmpSurfSize = srcSurfSize; - } - - rtViews = tmpRTView; - mDevice->OMSetRenderTargets(1, &rtViews, nullptr); - - mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView); - - // Premultiplied! - float shadowColor[4] = { aColor.r * aColor.a, aColor.g * aColor.a, - aColor.b * aColor.a, aColor.a }; - mPrivateData->mEffect->GetVariableByName("ShadowColor")->AsVector()-> - SetFloatVector(shadowColor); - - float pixelOffset = 1.0f / float(srcSurfSize.width); - float blurOffsetsH[9] = { 0, pixelOffset, -pixelOffset, - 2.0f * pixelOffset, -2.0f * pixelOffset, - 3.0f * pixelOffset, -3.0f * pixelOffset, - 4.0f * pixelOffset, - 4.0f * pixelOffset }; - - pixelOffset = 1.0f / float(tmpSurfSize.height); - float blurOffsetsV[9] = { 0, pixelOffset, -pixelOffset, - 2.0f * pixelOffset, -2.0f * pixelOffset, - 3.0f * pixelOffset, -3.0f * pixelOffset, - 4.0f * pixelOffset, - 4.0f * pixelOffset }; - - mPrivateData->mEffect->GetVariableByName("BlurOffsetsH")-> - SetRawValue(blurOffsetsH, 0, sizeof(blurOffsetsH)); - mPrivateData->mEffect->GetVariableByName("BlurOffsetsV")-> - SetRawValue(blurOffsetsV, 0, sizeof(blurOffsetsV)); - - mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")-> - GetPassByIndex(0)->Apply(0); - - mDevice->Draw(4, 0); - - viewport.MaxDepth = 1; - viewport.MinDepth = 0; - viewport.Height = mSize.height; - viewport.Width = mSize.width; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - - mDevice->RSSetViewports(1, &viewport); - - mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(tmpSRView); - - rtViews = destRTView; - mDevice->OMSetRenderTargets(1, &rtViews, nullptr); - - Point shadowDest = aDest + aOffset; - - mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((shadowDest.x / mSize.width) * 2.0f), - 1.0f - (shadowDest.y / mSize.height * 2.0f), - (Float(aSurface->GetSize().width) / mSize.width) * 2.0f, - (-Float(aSurface->GetSize().height) / mSize.height) * 2.0f)); - mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(0, 0, Float(srcSurfSize.width) / tmpSurfSize.width, - Float(srcSurfSize.height) / tmpSurfSize.height)); - - if (mPushedClips.size()) { - mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(maskSRView); - mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(shadowDest.x / mSize.width, shadowDest.y / mSize.height, - Float(aSurface->GetSize().width) / mSize.width, - Float(aSurface->GetSize().height) / mSize.height)); - mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")-> - GetPassByIndex(2)->Apply(0); - SetScissorToRect(&clipBounds); - } else { - mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")-> - GetPassByIndex(1)->Apply(0); - } - - mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), nullptr, 0xffffffff); - - mDevice->Draw(4, 0); - - srView = static_cast(aSurface)->GetSRView(); - if (!srView) { - return; - } - - mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((aDest.x / mSize.width) * 2.0f), - 1.0f - (aDest.y / mSize.height * 2.0f), - (Float(aSurface->GetSize().width) / mSize.width) * 2.0f, - (-Float(aSurface->GetSize().height) / mSize.height) * 2.0f)); - mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(static_cast(aSurface)->GetSRView()); - mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); - - if (mPushedClips.size()) { - mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(aDest.x / mSize.width, aDest.y / mSize.height, - Float(aSurface->GetSize().width) / mSize.width, - Float(aSurface->GetSize().height) / mSize.height)); - mPrivateData->mEffect->GetTechniqueByName("SampleMaskedTexture")-> - GetPassByIndex(0)->Apply(0); - // We've set the scissor rect here for the previous draw call. - } else { - mPrivateData->mEffect->GetTechniqueByName("SampleTexture")-> - GetPassByIndex(0)->Apply(0); - } - - mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), nullptr, 0xffffffff); - - mDevice->Draw(4, 0); -} - -void -DrawTargetD2D::ClearRect(const Rect &aRect) -{ - MarkChanged(); - PushClipRect(aRect); - - PopAllClips(); - - AutoSaveRestoreClippedOut restoreClippedOut(this); - - D2D1_RECT_F clipRect; - bool isPixelAligned; - bool pushedClip = false; - if (mTransform.IsRectilinear() && - GetDeviceSpaceClipRect(clipRect, isPixelAligned)) { - if (mTransformDirty || - !mTransform.IsIdentity()) { - mRT->SetTransform(D2D1::IdentityMatrix()); - mTransformDirty = true; - } - - mRT->PushAxisAlignedClip(clipRect, isPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); - pushedClip = true; - } else { - FlushTransformToRT(); - restoreClippedOut.Save(); - } - - mRT->Clear(D2D1::ColorF(0, 0.0f)); - - if (pushedClip) { - mRT->PopAxisAlignedClip(); - } - - PopClip(); - return; -} - -void -DrawTargetD2D::CopySurface(SourceSurface *aSurface, - const IntRect &aSourceRect, - const IntPoint &aDestination) -{ - MarkChanged(); - - Rect srcRect(Float(aSourceRect.x), Float(aSourceRect.y), - Float(aSourceRect.width), Float(aSourceRect.height)); - Rect dstRect(Float(aDestination.x), Float(aDestination.y), - Float(aSourceRect.width), Float(aSourceRect.height)); - - mRT->SetTransform(D2D1::IdentityMatrix()); - mTransformDirty = true; - mRT->PushAxisAlignedClip(D2DRect(dstRect), D2D1_ANTIALIAS_MODE_ALIASED); - mRT->Clear(D2D1::ColorF(0, 0.0f)); - mRT->PopAxisAlignedClip(); - - RefPtr bitmap = GetBitmapForSurface(aSurface, srcRect); - if (!bitmap) { - return; - } - - if (aSurface->GetFormat() == SurfaceFormat::A8) { - RefPtr brush; - mRT->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), - D2D1::BrushProperties(), getter_AddRefs(brush)); - mRT->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); - mRT->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS); - } else { - mRT->DrawBitmap(bitmap, D2DRect(dstRect), 1.0f, - D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, - D2DRect(srcRect)); - } -} - -void -DrawTargetD2D::FillRect(const Rect &aRect, - const Pattern &aPattern, - const DrawOptions &aOptions) -{ - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern); - - PrepareForDrawing(rt); - - rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode)); - - RefPtr brush = CreateBrushForPattern(aPattern, aOptions.mAlpha); - - if (brush) { - rt->FillRectangle(D2DRect(aRect), brush); - } - - FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, aRect); -} - -void -DrawTargetD2D::StrokeRect(const Rect &aRect, - const Pattern &aPattern, - const StrokeOptions &aStrokeOptions, - const DrawOptions &aOptions) -{ - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern); - - PrepareForDrawing(rt); - - rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode)); - - RefPtr brush = CreateBrushForPattern(aPattern, aOptions.mAlpha); - - RefPtr strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions); - - if (brush && strokeStyle) { - rt->DrawRectangle(D2DRect(aRect), brush, aStrokeOptions.mLineWidth, strokeStyle); - } - - FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, aRect); -} - -void -DrawTargetD2D::StrokeLine(const Point &aStart, - const Point &aEnd, - const Pattern &aPattern, - const StrokeOptions &aStrokeOptions, - const DrawOptions &aOptions) -{ - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern); - - PrepareForDrawing(rt); - - rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode)); - - RefPtr brush = CreateBrushForPattern(aPattern, aOptions.mAlpha); - - RefPtr strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions); - - if (brush && strokeStyle) { - rt->DrawLine(D2DPoint(aStart), D2DPoint(aEnd), brush, aStrokeOptions.mLineWidth, strokeStyle); - } - - FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, Float(mSize.width), Float(mSize.height))); -} - -void -DrawTargetD2D::Stroke(const Path *aPath, - const Pattern &aPattern, - const StrokeOptions &aStrokeOptions, - const DrawOptions &aOptions) -{ - if (aPath->GetBackendType() != BackendType::DIRECT2D) { - gfxDebug() << *this << ": Ignoring drawing call for incompatible path."; - return; - } - - const PathD2D *d2dPath = static_cast(aPath); - - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern); - - PrepareForDrawing(rt); - - rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode)); - - RefPtr brush = CreateBrushForPattern(aPattern, aOptions.mAlpha); - - RefPtr strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions); - - if (brush && strokeStyle) { - rt->DrawGeometry(d2dPath->mGeometry, brush, aStrokeOptions.mLineWidth, strokeStyle); - } - - FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, Float(mSize.width), Float(mSize.height))); -} - -void -DrawTargetD2D::Fill(const Path *aPath, - const Pattern &aPattern, - const DrawOptions &aOptions) -{ - if (aPath->GetBackendType() != BackendType::DIRECT2D) { - gfxDebug() << *this << ": Ignoring drawing call for incompatible path."; - return; - } - - const PathD2D *d2dPath = static_cast(aPath); - - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern); - - PrepareForDrawing(rt); - - rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode)); - - RefPtr brush = CreateBrushForPattern(aPattern, aOptions.mAlpha); - - if (brush) { - rt->FillGeometry(d2dPath->mGeometry, brush); - } - - Rect bounds; - if (aOptions.mCompositionOp != CompositionOp::OP_OVER) { - D2D1_RECT_F d2dbounds; - d2dPath->mGeometry->GetBounds(D2D1::IdentityMatrix(), &d2dbounds); - bounds = ToRect(d2dbounds); - } - FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, bounds); -} - -void -DrawTargetD2D::FillGlyphs(ScaledFont *aFont, - const GlyphBuffer &aBuffer, - const Pattern &aPattern, - const DrawOptions &aOptions, - const GlyphRenderingOptions* aRenderOptions) -{ - if (aFont->GetType() != FontType::DWRITE) { - gfxDebug() << *this << ": Ignoring drawing call for incompatible font."; - return; - } - - ScaledFontDWrite *font = static_cast(aFont); - - IDWriteRenderingParams *params = nullptr; - if (aRenderOptions) { - if (aRenderOptions->GetType() != FontType::DWRITE) { - gfxDebug() << *this << ": Ignoring incompatible GlyphRenderingOptions."; - // This should never happen. - MOZ_ASSERT(false); - } else { - params = static_cast(aRenderOptions)->mParams; - } - } - - AntialiasMode aaMode = font->GetDefaultAAMode(); - - if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) { - aaMode = aOptions.mAntialiasMode; - } - - if (mFormat == SurfaceFormat::B8G8R8A8 && mPermitSubpixelAA && - aOptions.mCompositionOp == CompositionOp::OP_OVER && aPattern.GetType() == PatternType::COLOR && - aaMode == AntialiasMode::SUBPIXEL) { - if (FillGlyphsManual(font, aBuffer, - static_cast(&aPattern)->mColor, - params, aOptions)) { - return; - } - } - - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern); - - PrepareForDrawing(rt); - - D2D1_TEXT_ANTIALIAS_MODE d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; - - switch (aaMode) { - case AntialiasMode::NONE: - d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED; - break; - case AntialiasMode::GRAY: - d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE; - break; - case AntialiasMode::SUBPIXEL: - d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; - break; - default: - d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; - } - - if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && - mFormat != SurfaceFormat::B8G8R8X8) { - d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE; - } - - rt->SetTextAntialiasMode(d2dAAMode); - - if (rt != mRT || params != mTextRenderingParams) { - rt->SetTextRenderingParams(params); - if (rt == mRT) { - mTextRenderingParams = params; - } - } - - RefPtr brush = CreateBrushForPattern(aPattern, aOptions.mAlpha); - - AutoDWriteGlyphRun autoRun; - DWriteGlyphRunFromGlyphs(aBuffer, font, &autoRun); - - if (brush) { - rt->DrawGlyphRun(D2D1::Point2F(), &autoRun, brush); - } - - FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, (Float)mSize.width, (Float)mSize.height)); -} - -void -DrawTargetD2D::Mask(const Pattern &aSource, - const Pattern &aMask, - const DrawOptions &aOptions) -{ - ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aSource); - - PrepareForDrawing(rt); - - RefPtr brush = CreateBrushForPattern(aSource, aOptions.mAlpha); - RefPtr maskBrush = CreateBrushForPattern(aMask, 1.0f); - - RefPtr layer; - - layer = GetCachedLayer(); - - rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), nullptr, - D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, - D2D1::IdentityMatrix(), - 1.0f, maskBrush), - layer); - - Rect rect(0, 0, (Float)mSize.width, (Float)mSize.height); - Matrix mat = mTransform; - mat.Invert(); - - rt->FillRectangle(D2DRect(mat.TransformBounds(rect)), brush); - PopCachedLayer(rt); - - FinalizeRTForOperation(aOptions.mCompositionOp, aSource, Rect(0, 0, (Float)mSize.width, (Float)mSize.height)); -} - -void -DrawTargetD2D::PushClip(const Path *aPath) -{ - if (aPath->GetBackendType() != BackendType::DIRECT2D) { - gfxDebug() << *this << ": Ignoring clipping call for incompatible path."; - return; - } - - mCurrentClipMaskTexture = nullptr; - mCurrentClippedGeometry = nullptr; - - RefPtr pathD2D = static_cast(const_cast(aPath)); - - PushedClip clip; - clip.mTransform = D2DMatrix(mTransform); - clip.mPath = pathD2D; - - pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds); - - clip.mLayer = GetCachedLayer(); - - mPushedClips.push_back(clip); - - // The transform of clips is relative to the world matrix, since we use the total - // transform for the clips, make the world matrix identity. - mRT->SetTransform(D2D1::IdentityMatrix()); - mTransformDirty = true; - - if (mClipsArePushed) { - PushD2DLayer(mRT, pathD2D->mGeometry, clip.mLayer, clip.mTransform); - } -} - -void -DrawTargetD2D::PushClipRect(const Rect &aRect) -{ - mCurrentClipMaskTexture = nullptr; - mCurrentClippedGeometry = nullptr; - if (!mTransform.IsRectilinear()) { - // Whoops, this isn't a rectangle in device space, Direct2D will not deal - // with this transform the way we want it to. - // See remarks: http://msdn.microsoft.com/en-us/library/dd316860%28VS.85%29.aspx - - RefPtr pathBuilder = CreatePathBuilder(); - pathBuilder->MoveTo(aRect.TopLeft()); - pathBuilder->LineTo(aRect.TopRight()); - pathBuilder->LineTo(aRect.BottomRight()); - pathBuilder->LineTo(aRect.BottomLeft()); - pathBuilder->Close(); - RefPtr path = pathBuilder->Finish(); - return PushClip(path); - } - - PushedClip clip; - Rect rect = mTransform.TransformBounds(aRect); - IntRect intRect; - clip.mIsPixelAligned = rect.ToIntRect(&intRect); - - // Do not store the transform, just store the device space rectangle directly. - clip.mBounds = D2DRect(rect); - - mPushedClips.push_back(clip); - - mRT->SetTransform(D2D1::IdentityMatrix()); - mTransformDirty = true; - - if (mClipsArePushed) { - mRT->PushAxisAlignedClip(clip.mBounds, clip.mIsPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); - } -} - -void -DrawTargetD2D::PopClip() -{ - mCurrentClipMaskTexture = nullptr; - mCurrentClippedGeometry = nullptr; - if (mClipsArePushed) { - if (mPushedClips.back().mLayer) { - PopCachedLayer(mRT); - } else { - mRT->PopAxisAlignedClip(); - } - } - mPushedClips.pop_back(); -} - -already_AddRefed -DrawTargetD2D::CreateSourceSurfaceFromData(unsigned char *aData, - const IntSize &aSize, - int32_t aStride, - SurfaceFormat aFormat) const -{ - RefPtr newSurf = new SourceSurfaceD2D(); - - if (!newSurf->InitFromData(aData, aSize, aStride, aFormat, mRT)) { - return nullptr; - } - - return newSurf.forget(); -} - -already_AddRefed -DrawTargetD2D::OptimizeSourceSurface(SourceSurface *aSurface) const -{ - if (aSurface->GetType() == SurfaceType::D2D1_BITMAP || - aSurface->GetType() == SurfaceType::D2D1_DRAWTARGET) { - RefPtr surface(aSurface); - return surface.forget(); - } - - RefPtr data = aSurface->GetDataSurface(); - - DataSourceSurface::MappedSurface map; - if (!data->Map(DataSourceSurface::MapType::READ, &map)) { - return nullptr; - } - - RefPtr newSurf = new SourceSurfaceD2D(); - bool success = newSurf->InitFromData(map.mData, data->GetSize(), map.mStride, data->GetFormat(), mRT); - - data->Unmap(); - - if (!success) { - return data.forget(); - } - return newSurf.forget(); -} - -already_AddRefed -DrawTargetD2D::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const -{ - if (aSurface.mType != NativeSurfaceType::D3D10_TEXTURE) { - gfxDebug() << *this << ": Failure to create source surface from non-D3D10 texture native surface."; - return nullptr; - } - RefPtr newSurf = new SourceSurfaceD2D(); - - if (!newSurf->InitFromTexture(static_cast(aSurface.mSurface), - aSurface.mFormat, - mRT)) - { - gfxWarning() << *this << ": Failed to create SourceSurface from texture."; - return nullptr; - } - - return newSurf.forget(); -} - -already_AddRefed -DrawTargetD2D::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const -{ - RefPtr newTarget = - new DrawTargetD2D(); - - if (!newTarget->Init(aSize, aFormat)) { - gfxDebug() << *this << ": Failed to create optimal draw target. Size: " << aSize; - return nullptr; - } - - return newTarget.forget(); -} - -already_AddRefed -DrawTargetD2D::CreatePathBuilder(FillRule aFillRule) const -{ - RefPtr path; - HRESULT hr = factory()->CreatePathGeometry(getter_AddRefs(path)); - - if (FAILED(hr)) { - gfxWarning() << "Failed to create Direct2D Path Geometry. Code: " << hexa(hr); - return nullptr; - } - - RefPtr sink; - hr = path->Open(getter_AddRefs(sink)); - if (FAILED(hr)) { - gfxWarning() << "Failed to access Direct2D Path Geometry. Code: " << hexa(hr); - return nullptr; - } - - if (aFillRule == FillRule::FILL_WINDING) { - sink->SetFillMode(D2D1_FILL_MODE_WINDING); - } - - return MakeAndAddRef(sink, path, aFillRule, BackendType::DIRECT2D); -} - -already_AddRefed -DrawTargetD2D::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, ExtendMode aExtendMode) const -{ - D2D1_GRADIENT_STOP *stops = new D2D1_GRADIENT_STOP[aNumStops]; - - for (uint32_t i = 0; i < aNumStops; i++) { - stops[i].position = rawStops[i].offset; - stops[i].color = D2DColor(rawStops[i].color); - } - - RefPtr stopCollection; - - HRESULT hr = - mRT->CreateGradientStopCollection(stops, aNumStops, - D2D1_GAMMA_2_2, D2DExtend(aExtendMode, Axis::BOTH), - getter_AddRefs(stopCollection)); - delete [] stops; - - if (FAILED(hr)) { - gfxWarning() << "Failed to create GradientStopCollection. Code: " << hexa(hr); - return nullptr; - } - - return MakeAndAddRef(stopCollection, Factory::GetDirect3D11Device()); -} - -already_AddRefed -DrawTargetD2D::CreateFilter(FilterType aType) -{ - RefPtr dc; - HRESULT hr = mRT->QueryInterface((ID2D1DeviceContext**)getter_AddRefs(dc)); - - if (SUCCEEDED(hr)) { - return FilterNodeD2D1::Create(dc, aType); - } - return FilterNodeSoftware::Create(aType); -} - -void* -DrawTargetD2D::GetNativeSurface(NativeSurfaceType aType) -{ - if (aType != NativeSurfaceType::D3D10_TEXTURE) { - return nullptr; - } - - return mTexture; -} - -/* - * Public functions - */ -bool -DrawTargetD2D::Init(const IntSize &aSize, SurfaceFormat aFormat) -{ - HRESULT hr; - - mSize = aSize; - mFormat = aFormat; - - if (!Factory::GetDirect3D10Device()) { - gfxCriticalError() << "Failed to Init Direct2D DrawTarget (No D3D10 Device set.)"; - return false; - } - mDevice = Factory::GetDirect3D10Device(); - - CD3D10_TEXTURE2D_DESC desc(DXGIFormat(aFormat), - mSize.width, - mSize.height, - 1, 1); - desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - - hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture)); - - if (FAILED(hr)) { - gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize))) << "Failed to init Direct2D DrawTarget. Size: " << mSize << " Code: " << hexa(hr); - return false; - } - - if (!InitD2DRenderTarget()) { - return false; - } - - mRT->Clear(D2D1::ColorF(0, 0)); - return true; -} - -bool -DrawTargetD2D::Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat) -{ - HRESULT hr; - - mTexture = aTexture; - mFormat = aFormat; - - if (!mTexture) { - gfxCriticalError() << "No valid texture for Direct2D draw target initialization."; - return false; - } - - RefPtr device; - mTexture->GetDevice(getter_AddRefs(device)); - - hr = device->QueryInterface((ID3D10Device1**)getter_AddRefs(mDevice)); - - if (FAILED(hr)) { - gfxCriticalError() << "Failed to get D3D10 device from texture." << " format " << (int)aFormat; - return false; - } - - D3D10_TEXTURE2D_DESC desc; - mTexture->GetDesc(&desc); - mSize.width = desc.Width; - mSize.height = desc.Height; - - return InitD2DRenderTarget(); -} - -// {0D398B49-AE7B-416F-B26D-EA3C137D1CF7} -static const GUID sPrivateDataD2D = -{ 0xd398b49, 0xae7b, 0x416f, { 0xb2, 0x6d, 0xea, 0x3c, 0x13, 0x7d, 0x1c, 0xf7 } }; - -bool -DrawTargetD2D::InitD3D10Data() -{ - HRESULT hr; - - UINT privateDataSize; - privateDataSize = sizeof(mPrivateData); - hr = mDevice->GetPrivateData(sPrivateDataD2D, &privateDataSize, &mPrivateData); - - if (SUCCEEDED(hr)) { - return true; - } - - mPrivateData = new PrivateD3D10DataD2D; - - decltype(D3D10CreateEffectFromMemory)* createD3DEffect; - HMODULE d3dModule = LoadLibraryW(L"d3d10_1.dll"); - createD3DEffect = (decltype(D3D10CreateEffectFromMemory)*) - GetProcAddress(d3dModule, "D3D10CreateEffectFromMemory"); - - hr = createD3DEffect((void*)d2deffect, sizeof(d2deffect), 0, mDevice, nullptr, getter_AddRefs(mPrivateData->mEffect)); - - if (FAILED(hr)) { - gfxWarning() << "Failed to initialize Direct2D required effects. Code: " << hexa(hr); - return false; - } - - privateDataSize = sizeof(mPrivateData); - mDevice->SetPrivateData(sPrivateDataD2D, privateDataSize, &mPrivateData); - - D3D10_INPUT_ELEMENT_DESC layout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, - }; - D3D10_PASS_DESC passDesc; - - mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->GetPassByIndex(0)->GetDesc(&passDesc); - - hr = mDevice->CreateInputLayout(layout, - sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC), - passDesc.pIAInputSignature, - passDesc.IAInputSignatureSize, - getter_AddRefs(mPrivateData->mInputLayout)); - - if (FAILED(hr)) { - gfxWarning() << "Failed to initialize Direct2D required InputLayout. Code: " << hexa(hr); - return false; - } - - D3D10_SUBRESOURCE_DATA data; - Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} }; - data.pSysMem = vertices; - CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER); - - hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mPrivateData->mVB)); - - if (FAILED(hr)) { - gfxWarning() << "Failed to initialize Direct2D required VertexBuffer. Code: " << hexa(hr); - return false; - } - - return true; -} - -/* - * Private helpers - */ -uint32_t -DrawTargetD2D::GetByteSize() const -{ - return mSize.width * mSize.height * BytesPerPixel(mFormat); -} - -already_AddRefed -DrawTargetD2D::GetCachedLayer() -{ - RefPtr layer; - - if (mCurrentCachedLayer < 5) { - if (!mCachedLayers[mCurrentCachedLayer]) { - mRT->CreateLayer(getter_AddRefs(mCachedLayers[mCurrentCachedLayer])); - mVRAMUsageDT += GetByteSize(); - } - layer = mCachedLayers[mCurrentCachedLayer]; - } else { - mRT->CreateLayer(getter_AddRefs(layer)); - } - - mCurrentCachedLayer++; - return layer.forget(); -} - -void -DrawTargetD2D::PopCachedLayer(ID2D1RenderTarget *aRT) -{ - aRT->PopLayer(); - mCurrentCachedLayer--; -} - -bool -DrawTargetD2D::InitD2DRenderTarget() -{ - if (!factory()) { - gfxCriticalError() << "No valid D2D factory available."; - return false; - } - - mRT = CreateRTForTexture(mTexture, mFormat); - - if (!mRT) { - return false; - } - - mRT->BeginDraw(); - - if (mFormat == SurfaceFormat::B8G8R8X8) { - mRT->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); - } - - mVRAMUsageDT += GetByteSize(); - - return InitD3D10Data(); -} - -void -DrawTargetD2D::PrepareForDrawing(ID2D1RenderTarget *aRT) -{ - if (!mClipsArePushed || aRT == mTempRT) { - if (mPushedClips.size()) { - // The transform of clips is relative to the world matrix, since we use the total - // transform for the clips, make the world matrix identity. - aRT->SetTransform(D2D1::IdentityMatrix()); - if (aRT == mRT) { - mTransformDirty = true; - mClipsArePushed = true; - } - PushClipsToRT(aRT); - } - } - FlushTransformToRT(); - MarkChanged(); - - if (aRT == mTempRT) { - mTempRT->SetTransform(D2DMatrix(mTransform)); - } -} - -void -DrawTargetD2D::MarkChanged() -{ - if (mSnapshot) { - if (mSnapshot->hasOneRef()) { - // Just destroy it, since no-one else knows about it. - mSnapshot = nullptr; - } else { - mSnapshot->DrawTargetWillChange(); - // The snapshot will no longer depend on this target. - MOZ_ASSERT(!mSnapshot); - } - } - if (mDependentTargets.size()) { - // Copy mDependentTargets since the Flush()es below will modify it. - TargetSet tmpTargets = mDependentTargets; - for (TargetSet::iterator iter = tmpTargets.begin(); - iter != tmpTargets.end(); iter++) { - (*iter)->Flush(); - } - // The Flush() should have broken all dependencies on this target. - MOZ_ASSERT(!mDependentTargets.size()); - } -} - -ID3D10BlendState* -DrawTargetD2D::GetBlendStateForOperator(CompositionOp aOperator) -{ - size_t operatorIndex = static_cast(aOperator); - if (mPrivateData->mBlendStates[operatorIndex]) { - return mPrivateData->mBlendStates[operatorIndex]; - } - - D3D10_BLEND_DESC desc; - - memset(&desc, 0, sizeof(D3D10_BLEND_DESC)); - - desc.AlphaToCoverageEnable = FALSE; - desc.BlendEnable[0] = TRUE; - desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; - desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD; - - switch (aOperator) { - case CompositionOp::OP_ADD: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE; - break; - case CompositionOp::OP_IN: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_DEST_ALPHA; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO; - break; - case CompositionOp::OP_OUT: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO; - break; - case CompositionOp::OP_ATOP: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_DEST_ALPHA; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; - break; - case CompositionOp::OP_DEST_IN: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_SRC_ALPHA; - break; - case CompositionOp::OP_DEST_OUT: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; - break; - case CompositionOp::OP_DEST_ATOP: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_SRC_ALPHA; - break; - case CompositionOp::OP_DEST_OVER: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE; - break; - case CompositionOp::OP_XOR: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; - break; - case CompositionOp::OP_SOURCE: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO; - break; - default: - desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE; - desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; - } - - mDevice->CreateBlendState(&desc, getter_AddRefs(mPrivateData->mBlendStates[operatorIndex])); - - return mPrivateData->mBlendStates[operatorIndex]; -} - -/* This function prepares the temporary RT for drawing and returns it when a - * drawing operation other than OVER is required. - */ -ID2D1RenderTarget* -DrawTargetD2D::GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern) -{ - if (aOperator == CompositionOp::OP_OVER && IsPatternSupportedByD2D(aPattern)) { - return mRT; - } - - PopAllClips(); - - if (aOperator > CompositionOp::OP_XOR) { - mRT->Flush(); - } - - if (mTempRT) { - mTempRT->Clear(D2D1::ColorF(0, 0)); - return mTempRT; - } - - EnsureViews(); - - if (!mRTView || !mSRView) { - gfxDebug() << *this << ": Failed to get required views. Defaulting to CompositionOp::OP_OVER."; - return mRT; - } - - mTempRT = CreateRTForTexture(mTempTexture, SurfaceFormat::B8G8R8A8); - - if (!mTempRT) { - return mRT; - } - - mVRAMUsageDT += GetByteSize(); - - mTempRT->BeginDraw(); - - mTempRT->Clear(D2D1::ColorF(0, 0)); - - return mTempRT; -} - -/* This function blends back the content of a drawing operation (drawn to an - * empty surface with OVER, so the surface now contains the source operation - * contents) to the rendertarget using the requested composition operation. - * In order to respect clip for operations which are unbound by their mask, - * the old content of the surface outside the clipped area may be blended back - * to the surface. - */ -void -DrawTargetD2D::FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds) -{ - if (aOperator == CompositionOp::OP_OVER && IsPatternSupportedByD2D(aPattern)) { - return; - } - - if (!mTempRT) { - return; - } - - PopClipsFromRT(mTempRT); - - mRT->Flush(); - mTempRT->Flush(); - - AutoSaveRestoreClippedOut restoreClippedOut(this); - - bool needsWriteBack = - !IsOperatorBoundByMask(aOperator) && mPushedClips.size(); - - if (needsWriteBack) { - restoreClippedOut.Save(); - } - - ID3D10RenderTargetView *rtViews = mRTView; - mDevice->OMSetRenderTargets(1, &rtViews, nullptr); - - UINT stride = sizeof(Vertex); - UINT offset = 0; - ID3D10Buffer *buff = mPrivateData->mVB; - - mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - mDevice->IASetVertexBuffers(0, 1, &buff, &stride, &offset); - mDevice->IASetInputLayout(mPrivateData->mInputLayout); - - D3D10_VIEWPORT viewport; - viewport.MaxDepth = 1; - viewport.MinDepth = 0; - viewport.Height = mSize.height; - viewport.Width = mSize.width; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - - RefPtr tmpTexture; - RefPtr mBckSRView; - - mDevice->RSSetViewports(1, &viewport); - mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(-1.0f, 1.0f, 2.0f, -2.0f)); - - if (IsPatternSupportedByD2D(aPattern)) { - mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); - mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(mSRView); - - // Handle the case where we blend with the backdrop - if (aOperator > CompositionOp::OP_XOR) { - IntSize size = mSize; - SurfaceFormat format = mFormat; - - CD3D10_TEXTURE2D_DESC desc(DXGIFormat(format), size.width, size.height, 1, 1); - desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - - HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(tmpTexture)); - if (FAILED(hr)) { - gfxWarning() << "Failed to create temporary texture to hold surface data."; - return; - } - - mDevice->CopyResource(tmpTexture, mTexture); - if (FAILED(hr)) { - gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr); - return; - } - - DrawTargetD2D::Flush(); - - hr = mDevice->CreateShaderResourceView(tmpTexture, nullptr, getter_AddRefs(mBckSRView)); - - if (FAILED(hr)) { - gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr); - return; - } - - unsigned int compop = (unsigned int)aOperator - (unsigned int)CompositionOp::OP_XOR; - mPrivateData->mEffect->GetVariableByName("bcktex")->AsShaderResource()->SetResource(mBckSRView); - mPrivateData->mEffect->GetVariableByName("blendop")->AsScalar()->SetInt(compop); - - if (aOperator > CompositionOp::OP_EXCLUSION) - mPrivateData->mEffect->GetTechniqueByName("SampleTextureForNonSeparableBlending")-> - GetPassByIndex(0)->Apply(0); - else if (aOperator > CompositionOp::OP_COLOR_DODGE) - mPrivateData->mEffect->GetTechniqueByName("SampleTextureForSeparableBlending_2")-> - GetPassByIndex(0)->Apply(0); - else - mPrivateData->mEffect->GetTechniqueByName("SampleTextureForSeparableBlending_1")-> - GetPassByIndex(0)->Apply(0); - } - else { - mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->GetPassByIndex(0)->Apply(0); - } - - } else if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) { - const RadialGradientPattern *pat = static_cast(&aPattern); - - if (pat->mCenter1 == pat->mCenter2 && pat->mRadius1 == pat->mRadius2) { - // Draw nothing! - return; - } - - mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(mSRView); - - SetupEffectForRadialGradient(pat); - } - - mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), nullptr, 0xffffffff); - - SetScissorToRect(nullptr); - mDevice->Draw(4, 0); -} - -static D2D1_RECT_F -IntersectRect(const D2D1_RECT_F& aRect1, const D2D1_RECT_F& aRect2) -{ - D2D1_RECT_F result; - result.left = max(aRect1.left, aRect2.left); - result.top = max(aRect1.top, aRect2.top); - result.right = min(aRect1.right, aRect2.right); - result.bottom = min(aRect1.bottom, aRect2.bottom); - - result.right = max(result.right, result.left); - result.bottom = max(result.bottom, result.top); - - return result; -} - -bool -DrawTargetD2D::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned) -{ - if (!mPushedClips.size()) { - return false; - } - - std::vector::iterator iter = mPushedClips.begin(); - if (iter->mPath) { - return false; - } - aClipRect = iter->mBounds; - aIsPixelAligned = iter->mIsPixelAligned; - - iter++; - for (;iter != mPushedClips.end(); iter++) { - if (iter->mPath) { - return false; - } - aClipRect = IntersectRect(aClipRect, iter->mBounds); - if (!iter->mIsPixelAligned) { - aIsPixelAligned = false; - } - } - return true; -} - -already_AddRefed -DrawTargetD2D::GetClippedGeometry(IntRect *aClipBounds) -{ - if (mCurrentClippedGeometry) { - *aClipBounds = mCurrentClipBounds; - RefPtr clippedGeometry(mCurrentClippedGeometry); - return clippedGeometry.forget(); - } - - mCurrentClipBounds = IntRect(IntPoint(0, 0), mSize); - - // if pathGeom is null then pathRect represents the path. - RefPtr pathGeom; - D2D1_RECT_F pathRect; - bool pathRectIsAxisAligned = false; - std::vector::iterator iter = mPushedClips.begin(); - - if (iter->mPath) { - pathGeom = GetTransformedGeometry(iter->mPath->GetGeometry(), iter->mTransform); - } else { - pathRect = iter->mBounds; - pathRectIsAxisAligned = iter->mIsPixelAligned; - } - - iter++; - for (;iter != mPushedClips.end(); iter++) { - // Do nothing but add it to the current clip bounds. - if (!iter->mPath && iter->mIsPixelAligned) { - mCurrentClipBounds.IntersectRect(mCurrentClipBounds, - IntRect(int32_t(iter->mBounds.left), int32_t(iter->mBounds.top), - int32_t(iter->mBounds.right - iter->mBounds.left), - int32_t(iter->mBounds.bottom - iter->mBounds.top))); - continue; - } - - if (!pathGeom) { - if (pathRectIsAxisAligned) { - mCurrentClipBounds.IntersectRect(mCurrentClipBounds, - IntRect(int32_t(pathRect.left), int32_t(pathRect.top), - int32_t(pathRect.right - pathRect.left), - int32_t(pathRect.bottom - pathRect.top))); - } - if (iter->mPath) { - // See if pathRect needs to go into the path geometry. - if (!pathRectIsAxisAligned) { - pathGeom = ConvertRectToGeometry(pathRect); - } else { - pathGeom = GetTransformedGeometry(iter->mPath->GetGeometry(), iter->mTransform); - } - } else { - pathRect = IntersectRect(pathRect, iter->mBounds); - pathRectIsAxisAligned = false; - continue; - } - } - - RefPtr newGeom; - factory()->CreatePathGeometry(getter_AddRefs(newGeom)); - - RefPtr currentSink; - newGeom->Open(getter_AddRefs(currentSink)); - - if (iter->mPath) { - pathGeom->CombineWithGeometry(iter->mPath->GetGeometry(), D2D1_COMBINE_MODE_INTERSECT, - iter->mTransform, currentSink); - } else { - RefPtr rectGeom = ConvertRectToGeometry(iter->mBounds); - pathGeom->CombineWithGeometry(rectGeom, D2D1_COMBINE_MODE_INTERSECT, - D2D1::IdentityMatrix(), currentSink); - } - - currentSink->Close(); - - pathGeom = newGeom.forget(); - } - - // For now we need mCurrentClippedGeometry to always be non-nullptr. This - // method might seem a little strange but it is just fine, if pathGeom is - // nullptr pathRect will always still contain 1 clip unaccounted for - // regardless of mCurrentClipBounds. - if (!pathGeom) { - pathGeom = ConvertRectToGeometry(pathRect); - } - mCurrentClippedGeometry = pathGeom.forget(); - *aClipBounds = mCurrentClipBounds; - RefPtr clippedGeometry(mCurrentClippedGeometry); - return clippedGeometry.forget(); -} - -already_AddRefed -DrawTargetD2D::CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat) -{ - HRESULT hr; - - RefPtr surface; - RefPtr rt; - - hr = aTexture->QueryInterface((IDXGISurface**)getter_AddRefs(surface)); - - if (FAILED(hr)) { - gfxCriticalError() << "Failed to QI texture to surface. Code: " << hexa(hr); - return nullptr; - } - - D3D10_TEXTURE2D_DESC desc; - aTexture->GetDesc(&desc); - - D2D1_ALPHA_MODE alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; - - if (aFormat == SurfaceFormat::B8G8R8X8 && aTexture == mTexture) { - alphaMode = D2D1_ALPHA_MODE_IGNORE; - } - - D2D1_RENDER_TARGET_PROPERTIES props = - D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(desc.Format, alphaMode)); - hr = factory()->CreateDxgiSurfaceRenderTarget(surface, props, getter_AddRefs(rt)); - - if (FAILED(hr)) { - gfxCriticalError() << "Failed to create D2D render target for texture. Code: " - << hexa(hr) << " " << mSize << " Format: " << uint32_t(aFormat); - return nullptr; - } - - return rt.forget(); -} - -void -DrawTargetD2D::EnsureViews() -{ - if (mTempTexture && mSRView && mRTView) { - return; - } - - HRESULT hr; - - CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, - mSize.width, - mSize.height, - 1, 1); - desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - - hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTempTexture)); - - if (FAILED(hr)) { - gfxWarning() << *this << "Failed to create temporary texture for rendertarget. Size: " - << mSize << " Code: " << hexa(hr); - return; - } - - hr = mDevice->CreateShaderResourceView(mTempTexture, nullptr, getter_AddRefs(mSRView)); - - if (FAILED(hr)) { - gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr); - return; - } - - hr = mDevice->CreateRenderTargetView(mTexture, nullptr, getter_AddRefs(mRTView)); - - if (FAILED(hr)) { - gfxWarning() << *this << "Failed to create rendertarget view for temp texture. Code: " << hexa(hr); - } -} - -void -DrawTargetD2D::PopAllClips() -{ - if (mClipsArePushed) { - PopClipsFromRT(mRT); - - mClipsArePushed = false; - } -} - -void -DrawTargetD2D::PushClipsToRT(ID2D1RenderTarget *aRT) -{ - for (std::vector::iterator iter = mPushedClips.begin(); - iter != mPushedClips.end(); iter++) { - if (iter->mLayer) { - PushD2DLayer(aRT, iter->mPath->mGeometry, iter->mLayer, iter->mTransform); - } else { - aRT->PushAxisAlignedClip(iter->mBounds, iter->mIsPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); - } - } -} - -void -DrawTargetD2D::PopClipsFromRT(ID2D1RenderTarget *aRT) -{ - for (int i = mPushedClips.size() - 1; i >= 0; i--) { - if (mPushedClips[i].mLayer) { - aRT->PopLayer(); - } else { - aRT->PopAxisAlignedClip(); - } - } -} - -void -DrawTargetD2D::EnsureClipMaskTexture(IntRect *aBounds) -{ - if (mCurrentClipMaskTexture || mPushedClips.empty()) { - *aBounds = mCurrentClipBounds; - return; - } - - RefPtr geometry = GetClippedGeometry(aBounds); - - CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_A8_UNORM, - mSize.width, - mSize.height, - 1, 1); - desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - - HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mCurrentClipMaskTexture)); - - if (FAILED(hr)) { - gfxWarning() << "Failed to create texture for ClipMask!"; - return; - } - - RefPtr rt = CreateRTForTexture(mCurrentClipMaskTexture, SurfaceFormat::A8); - - if (!rt) { - gfxWarning() << "Failed to create RT for ClipMask!"; - return; - } - - RefPtr brush; - rt->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), getter_AddRefs(brush)); - - rt->BeginDraw(); - rt->Clear(D2D1::ColorF(0, 0)); - rt->FillGeometry(geometry, brush); - rt->EndDraw(); -} - -bool -DrawTargetD2D::FillGlyphsManual(ScaledFontDWrite *aFont, - const GlyphBuffer &aBuffer, - const Color &aColor, - IDWriteRenderingParams *aParams, - const DrawOptions &aOptions) -{ - HRESULT hr; - - RefPtr params; - - if (aParams) { - params = aParams; - } else { - mRT->GetTextRenderingParams(getter_AddRefs(params)); - } - - DWRITE_RENDERING_MODE renderMode = DWRITE_RENDERING_MODE_DEFAULT; - if (params) { - hr = aFont->mFontFace->GetRecommendedRenderingMode( - (FLOAT)aFont->GetSize(), - 1.0f, - DWRITE_MEASURING_MODE_NATURAL, - params, - &renderMode); - if (FAILED(hr)) { - // this probably never happens, but let's play it safe - renderMode = DWRITE_RENDERING_MODE_DEFAULT; - } - } - - // Deal with rendering modes CreateGlyphRunAnalysis doesn't accept. - switch (renderMode) { - case DWRITE_RENDERING_MODE_ALIASED: - // ClearType texture creation will fail in this mode, so bail out - return false; - case DWRITE_RENDERING_MODE_DEFAULT: - // As per DWRITE_RENDERING_MODE documentation, pick Natural for font - // sizes under 16 ppem - if (aFont->GetSize() < 16.0f) { - renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; - } else { - renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; - } - break; - case DWRITE_RENDERING_MODE_OUTLINE: - renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; - break; - default: - break; - } - - DWRITE_MEASURING_MODE measureMode = - renderMode <= DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC ? DWRITE_MEASURING_MODE_GDI_CLASSIC : - renderMode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL ? DWRITE_MEASURING_MODE_GDI_NATURAL : - DWRITE_MEASURING_MODE_NATURAL; - - DWRITE_MATRIX mat = DWriteMatrixFromMatrix(mTransform); - - AutoDWriteGlyphRun autoRun; - DWriteGlyphRunFromGlyphs(aBuffer, aFont, &autoRun); - - RefPtr analysis; - hr = GetDWriteFactory()->CreateGlyphRunAnalysis(&autoRun, 1.0f, &mat, - renderMode, measureMode, 0, 0, getter_AddRefs(analysis)); - - if (FAILED(hr)) { - return false; - } - - RECT bounds; - hr = analysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds); - - if (bounds.bottom <= bounds.top || bounds.right <= bounds.left) { - // DWrite seems to do this sometimes. I'm not 100% sure why. See bug 758980. - gfxDebug() << "Empty alpha texture bounds! Falling back to regular drawing."; - return false; - } - IntRect rectBounds(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top); - IntRect surfBounds(IntPoint(0, 0), mSize); - - rectBounds.IntersectRect(rectBounds, surfBounds); - - if (rectBounds.IsEmpty()) { - // Nothing to do. - return true; - } - - RefPtr tex = CreateTextureForAnalysis(analysis, rectBounds); - - if (!tex) { - return false; - } - - RefPtr srView; - hr = mDevice->CreateShaderResourceView(tex, nullptr, getter_AddRefs(srView)); - - if (FAILED(hr)) { - return false; - } - - MarkChanged(); - - // Prepare our background texture for drawing. - PopAllClips(); - mRT->Flush(); - - SetupStateForRendering(); - - ID3D10EffectTechnique *technique = mPrivateData->mEffect->GetTechniqueByName("SampleTextTexture"); - - mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((Float(rectBounds.x) / mSize.width) * 2.0f), - 1.0f - (Float(rectBounds.y) / mSize.height * 2.0f), - (Float(rectBounds.width) / mSize.width) * 2.0f, - (-Float(rectBounds.height) / mSize.height) * 2.0f)); - mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); - FLOAT color[4] = { aColor.r, aColor.g, aColor.b, aColor.a }; - mPrivateData->mEffect->GetVariableByName("TextColor")->AsVector()-> - SetFloatVector(color); - - mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView); - - bool isMasking = false; - - IntRect clipBoundsStorage; - IntRect *clipBounds = nullptr; - - if (!mPushedClips.empty()) { - clipBounds = &clipBoundsStorage; - RefPtr geom = GetClippedGeometry(clipBounds); - - RefPtr rectGeom; - factory()->CreateRectangleGeometry(D2D1::RectF(Float(rectBounds.x), - Float(rectBounds.y), - Float(rectBounds.width + rectBounds.x), - Float(rectBounds.height + rectBounds.y)), - getter_AddRefs(rectGeom)); - - D2D1_GEOMETRY_RELATION relation; - if (FAILED(geom->CompareWithGeometry(rectGeom, D2D1::IdentityMatrix(), &relation)) || - relation != D2D1_GEOMETRY_RELATION_CONTAINS ) { - isMasking = true; - } - } - - if (isMasking) { - clipBounds = &clipBoundsStorage; - EnsureClipMaskTexture(clipBounds); - - RefPtr srViewMask; - hr = mDevice->CreateShaderResourceView(mCurrentClipMaskTexture, nullptr, getter_AddRefs(srViewMask)); - - if (FAILED(hr)) { - return false; - } - - mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(srViewMask); - - mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(Float(rectBounds.x) / mSize.width, Float(rectBounds.y) / mSize.height, - Float(rectBounds.width) / mSize.width, Float(rectBounds.height) / mSize.height)); - - technique->GetPassByIndex(1)->Apply(0); - } else { - technique->GetPassByIndex(0)->Apply(0); - } - - RefPtr rtView; - ID3D10RenderTargetView *rtViews; - mDevice->CreateRenderTargetView(mTexture, nullptr, getter_AddRefs(rtView)); - - rtViews = rtView; - mDevice->OMSetRenderTargets(1, &rtViews, nullptr); - SetScissorToRect(clipBounds); - mDevice->Draw(4, 0); - return true; -} - -already_AddRefed -DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha) -{ - if (!IsPatternSupportedByD2D(aPattern)) { - RefPtr colBrush; - mRT->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), getter_AddRefs(colBrush)); - return colBrush.forget(); - } - - if (aPattern.GetType() == PatternType::COLOR) { - RefPtr colBrush; - Color color = static_cast(&aPattern)->mColor; - mRT->CreateSolidColorBrush(D2D1::ColorF(color.r, color.g, - color.b, color.a), - D2D1::BrushProperties(aAlpha), - getter_AddRefs(colBrush)); - return colBrush.forget(); - } - if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) { - RefPtr gradBrush; - const LinearGradientPattern *pat = - static_cast(&aPattern); - - GradientStopsD2D *stops = static_cast(pat->mStops.get()); - - if (!stops) { - gfxDebug() << "No stops specified for gradient pattern."; - return nullptr; - } - - if (pat->mBegin == pat->mEnd) { - RefPtr colBrush; - uint32_t stopCount = stops->mStopCollection->GetGradientStopCount(); - vector d2dStops(stopCount); - stops->mStopCollection->GetGradientStops(&d2dStops.front(), stopCount); - mRT->CreateSolidColorBrush(d2dStops.back().color, - D2D1::BrushProperties(aAlpha), - getter_AddRefs(colBrush)); - return colBrush.forget(); - } - - mRT->CreateLinearGradientBrush(D2D1::LinearGradientBrushProperties(D2DPoint(pat->mBegin), - D2DPoint(pat->mEnd)), - D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)), - stops->mStopCollection, - getter_AddRefs(gradBrush)); - return gradBrush.forget(); - } - if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) { - RefPtr gradBrush; - const RadialGradientPattern *pat = - static_cast(&aPattern); - - GradientStopsD2D *stops = static_cast(pat->mStops.get()); - - if (!stops) { - gfxDebug() << "No stops specified for gradient pattern."; - return nullptr; - } - - // This will not be a complex radial gradient brush. - mRT->CreateRadialGradientBrush( - D2D1::RadialGradientBrushProperties(D2DPoint(pat->mCenter2), - D2DPoint(pat->mCenter1 - pat->mCenter2), - pat->mRadius2, pat->mRadius2), - D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)), - stops->mStopCollection, - getter_AddRefs(gradBrush)); - - return gradBrush.forget(); - } - if (aPattern.GetType() == PatternType::SURFACE) { - RefPtr bmBrush; - const SurfacePattern *pat = - static_cast(&aPattern); - - if (!pat->mSurface) { - gfxDebug() << "No source surface specified for surface pattern"; - return nullptr; - } - - RefPtr bitmap; - - Matrix mat = pat->mMatrix; - - RefPtr source = pat->mSurface; - - if (!pat->mSamplingRect.IsEmpty() && - (source->GetType() == SurfaceType::D2D1_BITMAP || - source->GetType() == SurfaceType::D2D1_DRAWTARGET)) { - IntRect samplingRect = pat->mSamplingRect; - - RefPtr dt = new DrawTargetD2D(); - if (!dt->Init(samplingRect.Size(), - source->GetFormat())) { - // FIXME: Uncomment assertion, bug 1068195 - // MOZ_ASSERT(false, "Invalid sampling rect size!"); - return nullptr; - } - - dt->CopySurface(source, samplingRect, IntPoint()); - source = dt->Snapshot(); - - mat.PreTranslate(samplingRect.x, samplingRect.y); - } - - switch (source->GetType()) { - case SurfaceType::D2D1_BITMAP: - { - SourceSurfaceD2D *surf = static_cast(source.get()); - - bitmap = surf->mBitmap; - - if (!bitmap) { - return nullptr; - } - } - break; - case SurfaceType::D2D1_DRAWTARGET: - { - SourceSurfaceD2DTarget *surf = - static_cast(source.get()); - bitmap = surf->GetBitmap(mRT); - AddDependencyOnSource(surf); - } - break; - default: - { - RefPtr dataSurf = source->GetDataSurface(); - if (!dataSurf) { - gfxWarning() << "Invalid surface type."; - return nullptr; - } - - IntRect sourceRect = pat->mSamplingRect; - if (sourceRect.IsEmpty()) { - sourceRect = IntRect(0, 0, source->GetSize().width, source->GetSize().height); - } - - bitmap = CreatePartialBitmapForSurface(dataSurf, mTransform, mSize, pat->mExtendMode, mat, mRT, &sourceRect); - if (!bitmap) { - RefPtr colBrush; - mRT->CreateSolidColorBrush(D2D1::ColorF(0, 0), getter_AddRefs(colBrush)); - return colBrush.forget(); - } - } - break; - } - - D2D1_EXTEND_MODE xRepeat = D2DExtend(pat->mExtendMode, Axis::X_AXIS); - D2D1_EXTEND_MODE yRepeat = D2DExtend(pat->mExtendMode, Axis::Y_AXIS); - HRESULT hr = mRT->CreateBitmapBrush(bitmap, - D2D1::BitmapBrushProperties(xRepeat, - yRepeat, - D2DFilter(pat->mFilter)), - D2D1::BrushProperties(aAlpha, D2DMatrix(mat)), - getter_AddRefs(bmBrush)); - if (FAILED(hr)) { - gfxCriticalError() << "[D2D] 1CreateBitmapBrush failure: " << hexa(hr); - return nullptr; - } - return bmBrush.forget(); - } - - gfxWarning() << "Invalid pattern type detected."; - return nullptr; -} - -already_AddRefed -DrawTargetD2D::CreateGradientTexture(const GradientStopsD2D *aStops) -{ - CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 4096, 1, 1, 1); - - std::vector rawStops; - rawStops.resize(aStops->mStopCollection->GetGradientStopCount()); - aStops->mStopCollection->GetGradientStops(&rawStops.front(), rawStops.size()); - - std::vector textureData; - textureData.resize(4096 * 4); - unsigned char *texData = &textureData.front(); - - float prevColorPos = 0; - float nextColorPos = 1.0f; - D2D1_COLOR_F prevColor = rawStops[0].color; - D2D1_COLOR_F nextColor = prevColor; - - if (rawStops.size() >= 2) { - nextColor = rawStops[1].color; - nextColorPos = rawStops[1].position; - } - - uint32_t stopPosition = 2; - - // Not the most optimized way but this will do for now. - for (int i = 0; i < 4096; i++) { - // The 4095 seems a little counter intuitive, but we want the gradient - // color at offset 0 at the first pixel, and at offset 1.0f at the last - // pixel. - float pos = float(i) / 4095; - - while (pos > nextColorPos) { - prevColor = nextColor; - prevColorPos = nextColorPos; - if (rawStops.size() > stopPosition) { - nextColor = rawStops[stopPosition].color; - nextColorPos = rawStops[stopPosition++].position; - } else { - nextColorPos = 1.0f; - } - } - - float interp; - - if (nextColorPos != prevColorPos) { - interp = (pos - prevColorPos) / (nextColorPos - prevColorPos); - } else { - interp = 0; - } - - Color newColor(prevColor.r + (nextColor.r - prevColor.r) * interp, - prevColor.g + (nextColor.g - prevColor.g) * interp, - prevColor.b + (nextColor.b - prevColor.b) * interp, - prevColor.a + (nextColor.a - prevColor.a) * interp); - - texData[i * 4] = (char)(255.0f * newColor.b); - texData[i * 4 + 1] = (char)(255.0f * newColor.g); - texData[i * 4 + 2] = (char)(255.0f * newColor.r); - texData[i * 4 + 3] = (char)(255.0f * newColor.a); - } - - D3D10_SUBRESOURCE_DATA data; - data.pSysMem = &textureData.front(); - data.SysMemPitch = 4096 * 4; - - RefPtr tex; - mDevice->CreateTexture2D(&desc, &data, getter_AddRefs(tex)); - - return tex.forget(); -} - -already_AddRefed -DrawTargetD2D::CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds) -{ - HRESULT hr; - - uint32_t bufferSize = aBounds.width * aBounds.height * 3; - - RECT bounds; - bounds.left = aBounds.x; - bounds.top = aBounds.y; - bounds.right = aBounds.x + aBounds.width; - bounds.bottom = aBounds.y + aBounds.height; - - // Add one byte so we can safely read a 32-bit int when copying the last - // 3 bytes. - BYTE *texture = new BYTE[bufferSize + 1]; - hr = aAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds, texture, bufferSize); - - if (FAILED(hr)) { - delete [] texture; - return nullptr; - } - - int alignedBufferSize = aBounds.width * aBounds.height * 4; - - // Create a one-off immutable texture from system memory. - BYTE *alignedTextureData = new BYTE[alignedBufferSize]; - for (int y = 0; y < aBounds.height; y++) { - for (int x = 0; x < aBounds.width; x++) { - // Copy 3 Bpp source to 4 Bpp destination memory used for - // texture creation. D3D10 has no 3 Bpp texture format we can - // use. - // - // Since we don't care what ends up in the alpha pixel of the - // destination, therefor we can simply copy a normal 32 bit - // integer each time, filling the alpha pixel of the destination - // with the first subpixel of the next pixel from the source. - *((int*)(alignedTextureData + (y * aBounds.width + x) * 4)) = - *((int*)(texture + (y * aBounds.width + x) * 3)); - } - } - - D3D10_SUBRESOURCE_DATA data; - - CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, - aBounds.width, aBounds.height, - 1, 1); - desc.Usage = D3D10_USAGE_IMMUTABLE; - - data.SysMemPitch = aBounds.width * 4; - data.pSysMem = alignedTextureData; - - RefPtr tex; - hr = mDevice->CreateTexture2D(&desc, &data, getter_AddRefs(tex)); - - delete [] alignedTextureData; - delete [] texture; - - if (FAILED(hr)) { - return nullptr; - } - - return tex.forget(); -} - -void -DrawTargetD2D::SetupEffectForRadialGradient(const RadialGradientPattern *aPattern) -{ - mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->GetPassByIndex(0)->Apply(0); - mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); - - float dimensions[] = { float(mSize.width), float(mSize.height), 0, 0 }; - mPrivateData->mEffect->GetVariableByName("dimensions")->AsVector()-> - SetFloatVector(dimensions); - - const GradientStopsD2D *stops = - static_cast(aPattern->mStops.get()); - - RefPtr tex = CreateGradientTexture(stops); - - RefPtr srView; - mDevice->CreateShaderResourceView(tex, nullptr, getter_AddRefs(srView)); - - mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView); - - Point dc = aPattern->mCenter2 - aPattern->mCenter1; - float dr = aPattern->mRadius2 - aPattern->mRadius1; - - float diffv[] = { dc.x, dc.y, dr, 0 }; - mPrivateData->mEffect->GetVariableByName("diff")->AsVector()-> - SetFloatVector(diffv); - - float center1[] = { aPattern->mCenter1.x, aPattern->mCenter1.y, dr, 0 }; - mPrivateData->mEffect->GetVariableByName("center1")->AsVector()-> - SetFloatVector(center1); - - mPrivateData->mEffect->GetVariableByName("radius1")->AsScalar()-> - SetFloat(aPattern->mRadius1); - mPrivateData->mEffect->GetVariableByName("sq_radius1")->AsScalar()-> - SetFloat(pow(aPattern->mRadius1, 2)); - - Matrix invTransform = mTransform; - - if (!invTransform.Invert()) { - // Bail if the matrix is singular. - return; - } - float matrix[] = { invTransform._11, invTransform._12, 0, 0, - invTransform._21, invTransform._22, 0, 0, - invTransform._31, invTransform._32, 1.0f, 0, - 0, 0, 0, 1.0f }; - - mPrivateData->mEffect->GetVariableByName("DeviceSpaceToUserSpace")-> - AsMatrix()->SetMatrix(matrix); - - float A = dc.x * dc.x + dc.y * dc.y - dr * dr; - - uint32_t offset = 0; - switch (stops->mStopCollection->GetExtendMode()) { - case D2D1_EXTEND_MODE_WRAP: - offset = 1; - break; - case D2D1_EXTEND_MODE_MIRROR: - offset = 2; - break; - default: - gfxWarning() << "This shouldn't happen! Invalid extend mode for gradient stops."; - } - - if (A == 0) { - mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")-> - GetPassByIndex(offset * 2 + 1)->Apply(0); - } else { - mPrivateData->mEffect->GetVariableByName("A")->AsScalar()->SetFloat(A); - mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")-> - GetPassByIndex(offset * 2)->Apply(0); - } -} - -void -DrawTargetD2D::SetupStateForRendering() -{ - UINT stride = sizeof(Vertex); - UINT offset = 0; - ID3D10Buffer *buff = mPrivateData->mVB; - - mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - mDevice->IASetVertexBuffers(0, 1, &buff, &stride, &offset); - mDevice->IASetInputLayout(mPrivateData->mInputLayout); - - D3D10_VIEWPORT viewport; - viewport.MaxDepth = 1; - viewport.MinDepth = 0; - viewport.Height = mSize.height; - viewport.Width = mSize.width; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - - mDevice->RSSetViewports(1, &viewport); -} - -ID2D1Factory* -DrawTargetD2D::factory() -{ - if (mFactory) { - return mFactory; - } - - D2D1CreateFactoryFunc createD2DFactory; - HMODULE d2dModule = LoadLibraryW(L"d2d1.dll"); - createD2DFactory = (D2D1CreateFactoryFunc) - GetProcAddress(d2dModule, "D2D1CreateFactory"); - - if (!createD2DFactory) { - gfxWarning() << "Failed to locate D2D1CreateFactory function."; - return nullptr; - } - - D2D1_FACTORY_OPTIONS options; -#ifdef _DEBUG - options.debugLevel = D2D1_DEBUG_LEVEL_WARNING; -#else - options.debugLevel = D2D1_DEBUG_LEVEL_NONE; -#endif - //options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; - - HRESULT hr = createD2DFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, - __uuidof(ID2D1Factory), - &options, - (void**)&mFactory); - - if (FAILED(hr)) { - gfxWarning() << "Failed to create Direct2D factory."; - } - - RefPtr factoryD2D1; - hr = mFactory->QueryInterface((ID2D1Factory1**)getter_AddRefs(factoryD2D1)); - if (SUCCEEDED(hr)) { - ExtendInputEffectD2D1::Register(factoryD2D1); - } - - return mFactory; -} - -void -DrawTargetD2D::CleanupD2D() -{ - if (mFactory) { - RefPtr factoryD2D1; - HRESULT hr = mFactory->QueryInterface((ID2D1Factory1**)getter_AddRefs(factoryD2D1)); - if (SUCCEEDED(hr)) { - ExtendInputEffectD2D1::Unregister(factoryD2D1); - } - - mFactory->Release(); - mFactory = nullptr; - } -} - -IDWriteFactory* -DrawTargetD2D::GetDWriteFactory() -{ - if (mDWriteFactory) { - return mDWriteFactory; - } - - decltype(DWriteCreateFactory)* createDWriteFactory; - HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll"); - createDWriteFactory = (decltype(DWriteCreateFactory)*) - GetProcAddress(dwriteModule, "DWriteCreateFactory"); - - if (!createDWriteFactory) { - gfxWarning() << "Failed to locate DWriteCreateFactory function."; - return nullptr; - } - - HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), - reinterpret_cast(&mDWriteFactory)); - - if (FAILED(hr)) { - gfxWarning() << "Failed to create DWrite Factory."; - } - - return mDWriteFactory; -} - -void -DrawTargetD2D::SetScissorToRect(IntRect *aRect) -{ - D3D10_RECT rect; - if (aRect) { - rect.left = aRect->x; - rect.right = aRect->XMost(); - rect.top = aRect->y; - rect.bottom = aRect->YMost(); - } else { - rect.left = rect.top = INT32_MIN; - rect.right = rect.bottom = INT32_MAX; - } - - mDevice->RSSetScissorRects(1, &rect); -} - -void -DrawTargetD2D::PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform) -{ - D2D1_LAYER_OPTIONS options = D2D1_LAYER_OPTIONS_NONE; - D2D1_LAYER_OPTIONS1 options1 = D2D1_LAYER_OPTIONS1_NONE; - - if (aRT->GetPixelFormat().alphaMode == D2D1_ALPHA_MODE_IGNORE) { - options = D2D1_LAYER_OPTIONS_INITIALIZE_FOR_CLEARTYPE; - options1 = D2D1_LAYER_OPTIONS1_IGNORE_ALPHA | D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND; - } - - RefPtr dc; - HRESULT hr = aRT->QueryInterface(IID_ID2D1DeviceContext, (void**)((ID2D1DeviceContext**)getter_AddRefs(dc))); - - if (FAILED(hr)) { - aRT->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), aGeometry, - D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, aTransform, - 1.0, nullptr, options), - aLayer); - } else { - dc->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), aGeometry, - D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, aTransform, - 1.0, nullptr, options1), - aLayer); - } -} - -} -} diff --git a/gfx/2d/DrawTargetD2D.h b/gfx/2d/DrawTargetD2D.h deleted file mode 100644 index 7c0a5b403e84..000000000000 --- a/gfx/2d/DrawTargetD2D.h +++ /dev/null @@ -1,290 +0,0 @@ -/* -*- 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/. */ - -#ifndef MOZILLA_GFX_DRAWTARGETD2D_H_ -#define MOZILLA_GFX_DRAWTARGETD2D_H_ - -#include "2D.h" -#include "PathD2D.h" -#include -#include "HelpersD2D.h" - -#include -#include - -#include - -struct IDWriteFactory; - -namespace mozilla { -namespace gfx { - -class SourceSurfaceD2DTarget; -class SourceSurfaceD2D; -class GradientStopsD2D; -class ScaledFontDWrite; - -const int32_t kLayerCacheSize = 5; - -struct PrivateD3D10DataD2D -{ - RefPtr mEffect; - RefPtr mInputLayout; - RefPtr mVB; - RefPtr mBlendStates[size_t(CompositionOp::OP_COUNT)]; -}; - -class DrawTargetD2D : public DrawTarget -{ -public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D, override) - DrawTargetD2D(); - virtual ~DrawTargetD2D(); - - virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; } - virtual BackendType GetBackendType() const override { return BackendType::DIRECT2D; } - virtual already_AddRefed Snapshot() override; - virtual IntSize GetSize() override { return mSize; } - - virtual void Flush() override; - virtual void DrawSurface(SourceSurface *aSurface, - const Rect &aDest, - const Rect &aSource, - const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), - const DrawOptions &aOptions = DrawOptions()) override; - virtual void DrawFilter(FilterNode *aNode, - const Rect &aSourceRect, - const Point &aDestPoint, - const DrawOptions &aOptions = DrawOptions()) override; - virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, - const Point &aDest, - const Color &aColor, - const Point &aOffset, - Float aSigma, - CompositionOp aOperator) override; - virtual void ClearRect(const Rect &aRect) override; - virtual void MaskSurface(const Pattern &aSource, - SourceSurface *aMask, - Point aOffset, - const DrawOptions &aOptions = DrawOptions()) override; - - - virtual void CopySurface(SourceSurface *aSurface, - const IntRect &aSourceRect, - const IntPoint &aDestination) override; - - virtual void FillRect(const Rect &aRect, - const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()) override; - virtual void StrokeRect(const Rect &aRect, - const Pattern &aPattern, - const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()) override; - virtual void StrokeLine(const Point &aStart, - const Point &aEnd, - const Pattern &aPattern, - const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()) override; - virtual void Stroke(const Path *aPath, - const Pattern &aPattern, - const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()) override; - virtual void Fill(const Path *aPath, - const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()) override; - virtual void FillGlyphs(ScaledFont *aFont, - const GlyphBuffer &aBuffer, - const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions(), - const GlyphRenderingOptions *aRenderingOptions = nullptr) override; - virtual void Mask(const Pattern &aSource, - const Pattern &aMask, - const DrawOptions &aOptions = DrawOptions()) override; - virtual void PushClip(const Path *aPath) override; - virtual void PushClipRect(const Rect &aRect) override; - virtual void PopClip() override; - - virtual already_AddRefed CreateSourceSurfaceFromData(unsigned char *aData, - const IntSize &aSize, - int32_t aStride, - SurfaceFormat aFormat) const override; - virtual already_AddRefed OptimizeSourceSurface(SourceSurface *aSurface) const override; - - virtual already_AddRefed - CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override; - - virtual already_AddRefed - CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override; - - virtual already_AddRefed CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override; - - virtual already_AddRefed - CreateGradientStops(GradientStop *aStops, - uint32_t aNumStops, - ExtendMode aExtendMode = ExtendMode::CLAMP) const override; - - virtual already_AddRefed CreateFilter(FilterType aType) override; - - virtual bool SupportsRegionClipping() const override { return false; } - - virtual void *GetNativeSurface(NativeSurfaceType aType) override; - - bool Init(const IntSize &aSize, SurfaceFormat aFormat); - bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); - bool InitD3D10Data(); - uint32_t GetByteSize() const; - already_AddRefed GetCachedLayer(); - void PopCachedLayer(ID2D1RenderTarget *aRT); - - already_AddRefed GetImageForSurface(SourceSurface *aSurface); - - static ID2D1Factory *factory(); - static void CleanupD2D(); - static IDWriteFactory *GetDWriteFactory(); - ID2D1RenderTarget *GetRT() { return mRT; } - - static uint32_t GetMaxSurfaceSize() { - return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; - } - - operator std::string() const { - std::stringstream stream; - stream << "DrawTargetD2D(" << this << ")"; - return stream.str(); - } - - static uint64_t mVRAMUsageDT; - static uint64_t mVRAMUsageSS; - -private: - already_AddRefed - GetBitmapForSurface(SourceSurface *aSurface, - Rect &aSource); - friend class AutoSaveRestoreClippedOut; - friend class SourceSurfaceD2DTarget; - - typedef std::unordered_set TargetSet; - - bool InitD2DRenderTarget(); - void PrepareForDrawing(ID2D1RenderTarget *aRT); - - // This function will mark the surface as changing, and make sure any - // copy-on-write snapshots are notified. - void MarkChanged(); - void FlushTransformToRT() { - if (mTransformDirty) { - mRT->SetTransform(D2DMatrix(mTransform)); - mTransformDirty = false; - } - } - void AddDependencyOnSource(SourceSurfaceD2DTarget* aSource); - - ID3D10BlendState *GetBlendStateForOperator(CompositionOp aOperator); - ID2D1RenderTarget *GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern); - void FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds); void EnsureViews(); - void PopAllClips(); - void PushClipsToRT(ID2D1RenderTarget *aRT); - void PopClipsFromRT(ID2D1RenderTarget *aRT); - - // This function ensures mCurrentClipMaskTexture contains a texture containing - // a mask corresponding with the current DrawTarget clip. See - // GetClippedGeometry for a description of aClipBounds. - void EnsureClipMaskTexture(IntRect *aClipBounds); - - bool FillGlyphsManual(ScaledFontDWrite *aFont, - const GlyphBuffer &aBuffer, - const Color &aColor, - IDWriteRenderingParams *aParams, - const DrawOptions &aOptions = DrawOptions()); - - already_AddRefed CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); - - // This returns the clipped geometry, in addition it returns aClipBounds which - // represents the intersection of all pixel-aligned rectangular clips that - // are currently set. The returned clipped geometry must be clipped by these - // bounds to correctly reflect the total clip. This is in device space. - already_AddRefed GetClippedGeometry(IntRect *aClipBounds); - - bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned); - - already_AddRefed CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); - - already_AddRefed CreateGradientTexture(const GradientStopsD2D *aStops); - already_AddRefed CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds); - - void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern); - void SetupStateForRendering(); - - // Set the scissor rect to a certain IntRects, resets the scissor rect to - // surface bounds when nullptr is specified. - void SetScissorToRect(IntRect *aRect); - - void PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform); - - static const uint32_t test = 4; - - IntSize mSize; - - RefPtr mDevice; - RefPtr mTexture; - RefPtr mCurrentClipMaskTexture; - RefPtr mCurrentClippedGeometry; - // This is only valid if mCurrentClippedGeometry is non-null. And will - // only be the intersection of all pixel-aligned retangular clips. This is in - // device space. - IntRect mCurrentClipBounds; - mutable RefPtr mRT; - - // We store this to prevent excessive SetTextRenderingParams calls. - RefPtr mTextRenderingParams; - - // Temporary texture and render target used for supporting alternative operators. - RefPtr mTempTexture; - RefPtr mRTView; - RefPtr mSRView; - RefPtr mTempRT; - RefPtr mTempRTView; - - // List of pushed clips. - struct PushedClip - { - RefPtr mLayer; - D2D1_RECT_F mBounds; - union { - // If mPath is non-nullptr, the mTransform member will be used, otherwise - // the mIsPixelAligned member is valid. - D2D1_MATRIX_3X2_F mTransform; - bool mIsPixelAligned; - }; - RefPtr mPath; - }; - std::vector mPushedClips; - - // We cache ID2D1Layer objects as it causes D2D to keep around textures that - // serve as the temporary surfaces for these operations. As texture creation - // is quite expensive this considerably improved performance. - // Careful here, RAII will not ensure destruction of the RefPtrs. - RefPtr mCachedLayers[kLayerCacheSize]; - uint32_t mCurrentCachedLayer; - - // The latest snapshot of this surface. This needs to be told when this - // target is modified. We keep it alive as a cache. - RefPtr mSnapshot; - // A list of targets we need to flush when we're modified. - TargetSet mDependentTargets; - // A list of targets which have this object in their mDependentTargets set - TargetSet mDependingOnTargets; - - // True of the current clip stack is pushed to the main RT. - bool mClipsArePushed; - PrivateD3D10DataD2D *mPrivateData; - static ID2D1Factory *mFactory; - static IDWriteFactory *mDWriteFactory; -}; - -} -} - -#endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */ diff --git a/gfx/2d/DrawTargetD2D1.cpp b/gfx/2d/DrawTargetD2D1.cpp index cb503ff493c4..8aa23c6b80aa 100644 --- a/gfx/2d/DrawTargetD2D1.cpp +++ b/gfx/2d/DrawTargetD2D1.cpp @@ -5,24 +5,32 @@ #include #include "DrawTargetD2D1.h" -#include "DrawTargetD2D.h" #include "FilterNodeSoftware.h" #include "GradientStopsD2D.h" #include "SourceSurfaceD2D1.h" -#include "SourceSurfaceD2D.h" #include "RadialGradientEffectD2D1.h" #include "HelpersD2D.h" #include "FilterNodeD2D1.h" +#include "ExtendInputEffectD2D1.h" #include "Tools.h" using namespace std; +// decltype is not usable for overloaded functions. +typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)( + D2D1_FACTORY_TYPE factoryType, + REFIID iid, + CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, + void **factory +); + namespace mozilla { namespace gfx { uint64_t DrawTargetD2D1::mVRAMUsageDT; uint64_t DrawTargetD2D1::mVRAMUsageSS; +IDWriteFactory *DrawTargetD2D1::mDWriteFactory; ID2D1Factory1* DrawTargetD2D1::mFactory = nullptr; ID2D1Factory1 *D2DFactory1() @@ -604,7 +612,7 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont, DWRITE_MEASURING_MODE_NATURAL, &userRect); RefPtr path; - D2DFactory()->CreatePathGeometry(getter_AddRefs(path)); + factory()->CreatePathGeometry(getter_AddRefs(path)); RefPtr sink; path->Open(getter_AddRefs(sink)); AddRectToSink(sink, userRect); @@ -1060,27 +1068,79 @@ DrawTargetD2D1::factory() return mFactory; } - ID2D1Factory* d2dFactory = D2DFactory(); - if (!d2dFactory) { + RefPtr factory; + D2D1CreateFactoryFunc createD2DFactory; + HMODULE d2dModule = LoadLibraryW(L"d2d1.dll"); + createD2DFactory = (D2D1CreateFactoryFunc) + GetProcAddress(d2dModule, "D2D1CreateFactory"); + + if (!createD2DFactory) { + gfxWarning() << "Failed to locate D2D1CreateFactory function."; return nullptr; } - HRESULT hr = d2dFactory->QueryInterface((ID2D1Factory1**)&mFactory); + D2D1_FACTORY_OPTIONS options; +#ifdef _DEBUG + options.debugLevel = D2D1_DEBUG_LEVEL_WARNING; +#else + options.debugLevel = D2D1_DEBUG_LEVEL_NONE; +#endif + //options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; - if (FAILED(hr)) { + HRESULT hr = createD2DFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, + __uuidof(ID2D1Factory), + &options, + getter_AddRefs(factory)); + + if (FAILED(hr) || !factory) { + gfxWarning() << "Failed to create Direct2D factory."; return nullptr; } + hr = factory->QueryInterface((ID2D1Factory1**)&mFactory); + if (FAILED(hr) || !mFactory) { + return nullptr; + } + + ExtendInputEffectD2D1::Register(mFactory); RadialGradientEffectD2D1::Register(mFactory); return mFactory; } +IDWriteFactory* +DrawTargetD2D1::GetDWriteFactory() +{ + if (mDWriteFactory) { + return mDWriteFactory; + } + + decltype(DWriteCreateFactory)* createDWriteFactory; + HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll"); + createDWriteFactory = (decltype(DWriteCreateFactory)*) + GetProcAddress(dwriteModule, "DWriteCreateFactory"); + + if (!createDWriteFactory) { + gfxWarning() << "Failed to locate DWriteCreateFactory function."; + return nullptr; + } + + HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), + reinterpret_cast(&mDWriteFactory)); + + if (FAILED(hr)) { + gfxWarning() << "Failed to create DWrite Factory."; + } + + return mDWriteFactory; +} + void DrawTargetD2D1::CleanupD2D() { if (mFactory) { RadialGradientEffectD2D1::Unregister(mFactory); + ExtendInputEffectD2D1::Unregister(mFactory); mFactory->Release(); mFactory = nullptr; } diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index 3d3fb0d63e0c..acbb445b590e 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -35,7 +35,6 @@ #endif #ifdef WIN32 -#include "DrawTargetD2D.h" #include "DrawTargetD2D1.h" #include "ScaledFontDWrite.h" #include "NativeFontResourceDWrite.h" @@ -161,7 +160,6 @@ int32_t LoggingPrefs::sGfxLogLevel = LOG_DEFAULT); #ifdef WIN32 -ID3D10Device1 *Factory::mD3D10Device; ID3D11Device *Factory::mD3D11Device; ID2D1Device *Factory::mD2D1Device; #endif @@ -315,15 +313,6 @@ Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFor RefPtr retVal; switch (aBackend) { #ifdef WIN32 - case BackendType::DIRECT2D: - { - RefPtr newTarget; - newTarget = new DrawTargetD2D(); - if (newTarget->Init(aSize, aFormat)) { - retVal = newTarget; - } - break; - } case BackendType::DIRECT2D1_1: { RefPtr newTarget; @@ -499,8 +488,6 @@ Factory::GetMaxSurfaceSize(BackendType aType) return DrawTargetSkia::GetMaxSurfaceSize(); #endif #ifdef WIN32 - case BackendType::DIRECT2D: - return DrawTargetD2D::GetMaxSurfaceSize(); case BackendType::DIRECT2D1_1: return DrawTargetD2D1::GetMaxSurfaceSize(); #endif @@ -611,87 +598,6 @@ Factory::CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB) #ifdef WIN32 -already_AddRefed -Factory::CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat) -{ - MOZ_ASSERT(aTexture); - - RefPtr newTarget; - - newTarget = new DrawTargetD2D(); - if (newTarget->Init(aTexture, aFormat)) { - RefPtr retVal = newTarget; - - if (mRecorder) { - retVal = new DrawTargetRecording(mRecorder, retVal, true); - } - - return retVal.forget(); - } - - gfxWarning() << "Failed to create draw target for D3D10 texture."; - - // Failed - return nullptr; -} - -already_AddRefed -Factory::CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA, - ID3D10Texture2D *aTextureB, - SurfaceFormat aFormat) -{ - MOZ_ASSERT(aTextureA && aTextureB); - RefPtr newTargetA; - RefPtr newTargetB; - - newTargetA = new DrawTargetD2D(); - if (!newTargetA->Init(aTextureA, aFormat)) { - gfxWarning() << "Failed to create dual draw target for D3D10 texture."; - return nullptr; - } - - newTargetB = new DrawTargetD2D(); - if (!newTargetB->Init(aTextureB, aFormat)) { - gfxWarning() << "Failed to create new draw target for D3D10 texture."; - return nullptr; - } - - RefPtr newTarget = - new DrawTargetDual(newTargetA, newTargetB); - - RefPtr retVal = newTarget; - - if (mRecorder) { - retVal = new DrawTargetRecording(mRecorder, retVal); - } - - return retVal.forget(); -} - -void -Factory::SetDirect3D10Device(ID3D10Device1 *aDevice) -{ - // do not throw on failure; return error codes and disconnect the device - // On Windows 8 error codes are the default, but on Windows 7 the - // default is to throw (or perhaps only with some drivers?) - if (aDevice) { - aDevice->SetExceptionMode(0); - } - mD3D10Device = aDevice; -} - -ID3D10Device1* -Factory::GetDirect3D10Device() -{ -#ifdef DEBUG - if (mD3D10Device) { - UINT mode = mD3D10Device->GetExceptionMode(); - MOZ_ASSERT(0 == mode); - } -#endif - return mD3D10Device; -} - already_AddRefed Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat) { @@ -767,13 +673,13 @@ Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams) uint64_t Factory::GetD2DVRAMUsageDrawTarget() { - return DrawTargetD2D::mVRAMUsageDT; + return DrawTargetD2D1::mVRAMUsageDT; } uint64_t Factory::GetD2DVRAMUsageSourceSurface() { - return DrawTargetD2D::mVRAMUsageSS; + return DrawTargetD2D1::mVRAMUsageSS; } void @@ -784,7 +690,6 @@ Factory::D2DCleanup() mD2D1Device = nullptr; } DrawTargetD2D1::CleanupD2D(); - DrawTargetD2D::CleanupD2D(); } already_AddRefed diff --git a/gfx/2d/FilterNodeD2D1.cpp b/gfx/2d/FilterNodeD2D1.cpp index c7f798e5bbcb..56c952990157 100644 --- a/gfx/2d/FilterNodeD2D1.cpp +++ b/gfx/2d/FilterNodeD2D1.cpp @@ -8,9 +8,6 @@ #include "Logging.h" #include "SourceSurfaceD2D1.h" -#include "SourceSurfaceD2D.h" -#include "SourceSurfaceD2DTarget.h" -#include "DrawTargetD2D.h" #include "DrawTargetD2D1.h" #include "ExtendInputEffectD2D1.h" @@ -159,8 +156,6 @@ already_AddRefed GetImageForSourceSurface(DrawTarget *aDT, SourceSur switch (aDT->GetBackendType()) { case BackendType::DIRECT2D1_1: return static_cast(aDT)->GetImageForSurface(aSurface, ExtendMode::CLAMP); - case BackendType::DIRECT2D: - return static_cast(aDT)->GetImageForSurface(aSurface); default: gfxDevCrash(LogReason::FilterNodeD2D1Backend) << "Unknown draw target type! " << (int)aDT->GetBackendType(); return nullptr; diff --git a/gfx/2d/HelpersD2D.h b/gfx/2d/HelpersD2D.h index bde54fc65070..869003a17fe4 100644 --- a/gfx/2d/HelpersD2D.h +++ b/gfx/2d/HelpersD2D.h @@ -25,9 +25,8 @@ namespace mozilla { namespace gfx { -ID2D1Factory* D2DFactory(); - ID2D1Factory1* D2DFactory1(); +static ID2D1Factory* D2DFactory() { return D2DFactory1(); } static inline D2D1_POINT_2F D2DPoint(const Point &aPoint) { diff --git a/gfx/2d/NativeFontResourceDWrite.cpp b/gfx/2d/NativeFontResourceDWrite.cpp index 10b0486de832..92ac6e884075 100644 --- a/gfx/2d/NativeFontResourceDWrite.cpp +++ b/gfx/2d/NativeFontResourceDWrite.cpp @@ -8,7 +8,7 @@ #include -#include "DrawTargetD2D.h" +#include "DrawTargetD2D1.h" #include "Logging.h" #include "mozilla/RefPtr.h" @@ -69,7 +69,7 @@ public: { if (!mInstance) { mInstance = new DWriteFontFileLoader(); - DrawTargetD2D::GetDWriteFactory()-> + DrawTargetD2D1::GetDWriteFactory()-> RegisterFontFileLoader(mInstance); } return mInstance; @@ -221,7 +221,7 @@ already_AddRefed NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo) { - IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory(); + IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory(); if (!factory) { gfxWarning() << "Failed to get DWrite Factory."; return nullptr; diff --git a/gfx/2d/PathD2D.cpp b/gfx/2d/PathD2D.cpp index 59e7e82c14e7..eb62595a2617 100644 --- a/gfx/2d/PathD2D.cpp +++ b/gfx/2d/PathD2D.cpp @@ -6,7 +6,7 @@ #include "PathD2D.h" #include "HelpersD2D.h" #include -#include "DrawTargetD2D.h" +#include "DrawTargetD2D1.h" #include "Logging.h" namespace mozilla { @@ -351,7 +351,7 @@ already_AddRefed PathD2D::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const { RefPtr path; - HRESULT hr = DrawTargetD2D::factory()->CreatePathGeometry(getter_AddRefs(path)); + HRESULT hr = DrawTargetD2D1::factory()->CreatePathGeometry(getter_AddRefs(path)); if (FAILED(hr)) { gfxWarning() << "Failed to create PathGeometry. Code: " << hexa(hr); diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp index 6da47bf4d066..a9c9e8f80512 100644 --- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -3,7 +3,7 @@ * 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 "DrawTargetD2D.h" +#include "DrawTargetD2D1.h" #include "ScaledFontDWrite.h" #include "PathD2D.h" @@ -120,7 +120,7 @@ ScaledFontDWrite::GetSkTypeface() { MOZ_ASSERT(mFont); if (!mTypeface) { - IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory(); + IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory(); mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily); } return mTypeface; diff --git a/gfx/2d/SourceSurfaceD2D.cpp b/gfx/2d/SourceSurfaceD2D.cpp deleted file mode 100644 index 650b54473b9e..000000000000 --- a/gfx/2d/SourceSurfaceD2D.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* -*- 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 -SourceSurfaceD2D::GetDataSurface() -{ - RefPtr 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, getter_AddRefs(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 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, getter_AddRefs(mBitmap)); - - if (FAILED(hr)) { - gfxWarning() << "Failed to create SharedBitmap. Code: " << hexa(hr); - return false; - } - - aTexture->GetDevice(getter_AddRefs(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 sourceTexture; - HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, - getter_AddRefs(sourceTexture)); - if (FAILED(hr)) { - gfxWarning() << "Failed to create texture. Code: " << hexa(hr); - return; - } - - RefPtr dxgiSurface; - hr = sourceTexture->QueryInterface((IDXGISurface**)getter_AddRefs(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 renderTarget; - hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface, - &rtProps, - getter_AddRefs(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 brush; - renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), getter_AddRefs(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, getter_AddRefs(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(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; - } -} - -} -} diff --git a/gfx/2d/SourceSurfaceD2D.h b/gfx/2d/SourceSurfaceD2D.h deleted file mode 100644 index 22ee5f125f94..000000000000 --- a/gfx/2d/SourceSurfaceD2D.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- 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/. */ - -#ifndef MOZILLA_GFX_SOURCESURFACED2D_H_ -#define MOZILLA_GFX_SOURCESURFACED2D_H_ - -#include "2D.h" -#include "HelpersD2D.h" -#include - -namespace mozilla { -namespace gfx { - -class DataSourceSurfaceD2D; - -class SourceSurfaceD2D : public SourceSurface -{ -public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2D) - SourceSurfaceD2D(); - ~SourceSurfaceD2D(); - - virtual SurfaceType GetType() const { return SurfaceType::D2D1_BITMAP; } - virtual IntSize GetSize() const; - virtual SurfaceFormat GetFormat() const; - virtual bool IsValid() const; - - virtual already_AddRefed GetDataSurface(); - - ID2D1Bitmap *GetBitmap() { return mBitmap; } - - bool InitFromData(unsigned char *aData, - const IntSize &aSize, - int32_t aStride, - SurfaceFormat aFormat, - ID2D1RenderTarget *aRT); - bool InitFromTexture(ID3D10Texture2D *aTexture, - SurfaceFormat aFormat, - ID2D1RenderTarget *aRT); -private: - friend class DrawTargetD2D; - friend class DataSourceSurfaceD2D; - - uint32_t GetByteSize() const; - - RefPtr mBitmap; - // We need to keep this pointer here to check surface validity. - RefPtr mDevice; - SurfaceFormat mFormat; - IntSize mSize; -}; - - -class DataSourceSurfaceD2D : public DataSourceSurface -{ -public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2D) - DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface); - virtual ~DataSourceSurfaceD2D(); - - virtual unsigned char* GetData(); - virtual int32_t Stride(); - virtual IntSize GetSize() const; - virtual SurfaceFormat GetFormat() const; - virtual bool Map(MapType, MappedSurface *aMappedSurface); - virtual void Unmap(); - - bool IsValid() - { - return mTexture; - } - -private: - void EnsureMappedTexture(); - - RefPtr mTexture; - - D3D10_MAPPED_TEXTURE2D mData; - - SurfaceFormat mFormat; - IntSize mSize; - bool mMapped; -}; - -} -} - -#endif /* MOZILLA_GFX_SOURCESURFACED2D_H_ */ diff --git a/gfx/2d/SourceSurfaceD2DTarget.cpp b/gfx/2d/SourceSurfaceD2DTarget.cpp deleted file mode 100644 index 464a64f42304..000000000000 --- a/gfx/2d/SourceSurfaceD2DTarget.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* -*- 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 - -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 -SourceSurfaceD2DTarget::GetDataSurface() -{ - RefPtr 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; - - if (!Factory::GetDirect3D10Device()) { - gfxCriticalError() << "Invalid D3D10 device in D2D target surface (GDS)"; - return nullptr; - } - - HRESULT hr = Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(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(mTexture.get()); - } - return nullptr; -} - -ID3D10ShaderResourceView* -SourceSurfaceD2DTarget::GetSRView() -{ - if (mSRView) { - return mSRView; - } - - if (!Factory::GetDirect3D10Device()) { - gfxCriticalError() << "Invalid D3D10 device in D2D target surface (SRV)"; - return nullptr; - } - - HRESULT hr = Factory::GetDirect3D10Device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView)); - - if (FAILED(hr)) { - gfxWarning() << "Failed to create ShaderResourceView. Code: " << hexa(hr); - } - - return mSRView; -} - -void -SourceSurfaceD2DTarget::DrawTargetWillChange() -{ - RefPtr 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, getter_AddRefs(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 surf; - hr = mTexture->QueryInterface((IDXGISurface**)getter_AddRefs(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, getter_AddRefs(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)), - getter_AddRefs(mBitmap)); - - if (FAILED(hr)) { - gfxWarning() << "Failed in CreateBitmap. Code: " << hexa(hr); - return nullptr; - } - - RefPtr 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 surface; - - hr = mTexture->QueryInterface((IDXGISurface**)getter_AddRefs(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, getter_AddRefs(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; - } -} - -} -} diff --git a/gfx/2d/SourceSurfaceD2DTarget.h b/gfx/2d/SourceSurfaceD2DTarget.h deleted file mode 100644 index 82b5b20778c7..000000000000 --- a/gfx/2d/SourceSurfaceD2DTarget.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- 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/. */ - -#ifndef MOZILLA_GFX_SOURCESURFACED2DTARGET_H_ -#define MOZILLA_GFX_SOURCESURFACED2DTARGET_H_ - -#include "2D.h" -#include "HelpersD2D.h" -#include -#include - -namespace mozilla { -namespace gfx { - -class DrawTargetD2D; - -class SourceSurfaceD2DTarget : public SourceSurface -{ -public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2DTarget) - SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget, ID3D10Texture2D* aTexture, - SurfaceFormat aFormat); - ~SourceSurfaceD2DTarget(); - - virtual SurfaceType GetType() const { return SurfaceType::D2D1_DRAWTARGET; } - virtual IntSize GetSize() const; - virtual SurfaceFormat GetFormat() const; - virtual already_AddRefed GetDataSurface(); - virtual void *GetNativeSurface(NativeSurfaceType aType); - - DrawTargetD2D* GetDT() { return mDrawTarget; } - ID2D1Bitmap *GetBitmap(ID2D1RenderTarget *aRT); - -private: - friend class DrawTargetD2D; - - ID3D10ShaderResourceView *GetSRView(); - - // This function is called by the draw target this texture belongs to when - // it is about to be changed. The texture will be required to make a copy - // of itself when this happens. - void DrawTargetWillChange(); - - // This will mark the surface as no longer depending on its drawtarget, - // this may happen on destruction or copying. - void MarkIndependent(); - - RefPtr mSRView; - RefPtr mBitmap; - // Non-null if this is a "lazy copy" of the given draw target. - // Null if we've made a copy. The target is not kept alive, otherwise we'd - // have leaks since it might keep us alive. If the target is destroyed, it - // will notify us. - DrawTargetD2D* mDrawTarget; - mutable RefPtr mTexture; - SurfaceFormat mFormat; - bool mOwnsCopy; -}; - -class DataSourceSurfaceD2DTarget : public DataSourceSurface -{ -public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2DTarget) - DataSourceSurfaceD2DTarget(SurfaceFormat aFormat); - ~DataSourceSurfaceD2DTarget(); - - virtual SurfaceType GetType() const { return SurfaceType::DATA; } - virtual IntSize GetSize() const; - virtual SurfaceFormat GetFormat() const; - virtual uint8_t *GetData(); - virtual int32_t Stride(); - virtual bool Map(MapType, MappedSurface *aMappedSurface); - virtual void Unmap(); - -private: - friend class SourceSurfaceD2DTarget; - void EnsureMapped(); - - mutable RefPtr mTexture; - SurfaceFormat mFormat; - D3D10_MAPPED_TEXTURE2D mMap; - bool mMapped; -}; - -} -} - -#endif /* MOZILLA_GFX_SOURCESURFACED2DTARGET_H_ */ diff --git a/gfx/2d/Types.h b/gfx/2d/Types.h index 3da1523b50d8..11199947da3e 100644 --- a/gfx/2d/Types.h +++ b/gfx/2d/Types.h @@ -123,7 +123,7 @@ enum class DrawTargetType : int8_t { enum class BackendType : int8_t { NONE = 0, - DIRECT2D, + DIRECT2D, // Used for version independent D2D objects. COREGRAPHICS, COREGRAPHICS_ACCELERATED, CAIRO, diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index e945563ecd68..eb674d531d21 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -66,7 +66,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'): ] elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': SOURCES += [ - 'DrawTargetD2D.cpp', 'DrawTargetD2D1.cpp', 'ExtendInputEffectD2D1.cpp', 'FilterNodeD2D1.cpp', @@ -77,9 +76,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': 'RadialGradientEffectD2D1.cpp', 'ScaledFontDWrite.cpp', 'ScaledFontWin.cpp', - 'SourceSurfaceD2D.cpp', 'SourceSurfaceD2D1.cpp', - 'SourceSurfaceD2DTarget.cpp', ] DEFINES['WIN32'] = True