/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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"2D.h" #include"Swizzle.h"
#ifdef USE_CAIRO # include "DrawTargetCairo.h" # include "PathCairo.h" # include "SourceSurfaceCairo.h" #endif
#ifdefined(WIN32) # include "ScaledFontWin.h" # include "NativeFontResourceGDI.h" # include "UnscaledFontGDI.h" #endif
#ifdef XP_DARWIN # include "ScaledFontMac.h" # include "NativeFontResourceMac.h" # include "UnscaledFontMac.h" #endif
#ifdef MOZ_WIDGET_GTK # include "ScaledFontFontconfig.h" # include "NativeFontResourceFreeType.h" # include "UnscaledFontFreeType.h" #endif
#ifdef MOZ_WIDGET_ANDROID # include "ScaledFontFreeType.h" # include "NativeFontResourceFreeType.h" # include "UnscaledFontFreeType.h" #endif
#ifdef WIN32 # include "DrawTargetD2D1.h" # include "PathD2D.h" # include "ScaledFontDWrite.h" # include "NativeFontResourceDWrite.h" # include "UnscaledFontDWrite.h" # include <d3d10_1.h> # include <stdlib.h> # include "HelpersD2D.h" # include "DXVA2Manager.h" # include "ImageContainer.h" # include "mozilla/layers/LayersSurfaces.h" # include "mozilla/layers/TextureD3D11.h" # include "nsWindowsHelpers.h" #endif
// The following code was largely taken from xpcom/glue/SSE.cpp and // made a little simpler. enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 };
#ifdef HAVE_CPUID_H
# if !(defined(__SSE2__) || defined(_M_X64) || \
(defined(_M_IX86_FP) && _M_IX86_FP >= 2)) || \
!defined(__SSE4__) // cpuid.h is available on gcc 4.3 and higher on i386 and x86_64 # include <cpuid.h>
// If the size is "reasonable", we want gfxCriticalError to assert, so // this is the option set up for it. inlineint LoggerOptionsBasedOnSize(const IntSize& aSize) { return CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize));
}
// reject images with sides bigger than limit if (extentLimit && (sz.width > extentLimit || sz.height > extentLimit)) {
gfxDebug() << "Surface size too large (exceeds extent limit)!"; returnfalse;
}
// assuming 4 bytes per pixel, make sure the allocation size // doesn't overflow a int32_t either
CheckedInt<int32_t> stride = GetAlignedStride<16>(sz.width, 4); if (!stride.isValid() || stride.value() == 0) {
gfxDebug() << "Surface size too large (stride overflows int32_t)!"; returnfalse;
}
CheckedInt<int32_t> numBytes = stride * sz.height; if (!numBytes.isValid()) {
gfxDebug()
<< "Surface size too large (allocation size would overflow int32_t)!"; returnfalse;
}
if (allocLimit && allocLimit < numBytes.value()) {
gfxDebug() << "Surface size too large (exceeds allocation limit)!"; returnfalse;
}
returntrue;
}
already_AddRefed<DrawTarget> Factory::CreateDrawTarget(BackendType aBackend, const IntSize& aSize,
SurfaceFormat aFormat) { if (!AllowedSurfaceSize(aSize)) {
gfxCriticalError(LoggerOptionsBasedOnSize(aSize))
<< "Failed to allocate a surface due to invalid size (CDT) " << aSize; return nullptr;
}
RefPtr<DrawTarget> retVal; switch (aBackend) { #ifdef WIN32 case BackendType::DIRECT2D1_1: {
RefPtr<DrawTargetD2D1> newTarget;
newTarget = new DrawTargetD2D1(); if (newTarget->Init(aSize, aFormat)) {
retVal = newTarget;
} break;
} #endif case BackendType::SKIA: {
RefPtr<DrawTargetSkia> newTarget;
newTarget = new DrawTargetSkia(); if (newTarget->Init(aSize, aFormat)) {
retVal = newTarget;
} break;
} #ifdef USE_CAIRO case BackendType::CAIRO: {
RefPtr<DrawTargetCairo> newTarget;
newTarget = new DrawTargetCairo(); if (newTarget->Init(aSize, aFormat)) {
retVal = newTarget;
} break;
} #endif default: return nullptr;
}
if (!dt->Init(aDrawTarget, aTileOrigin)) { return nullptr;
}
return dt.forget();
}
bool Factory::DoesBackendSupportDataDrawtarget(BackendType aType) { switch (aType) { case BackendType::DIRECT2D: case BackendType::DIRECT2D1_1: case BackendType::RECORDING: case BackendType::NONE: case BackendType::BACKEND_LAST: case BackendType::WEBRENDER_TEXT: case BackendType::WEBGL: returnfalse; case BackendType::CAIRO: case BackendType::SKIA: returntrue;
}
returnfalse;
}
uint32_t Factory::GetMaxSurfaceSize(BackendType aType) { switch (aType) { case BackendType::CAIRO: return DrawTargetCairo::GetMaxSurfaceSize(); case BackendType::SKIA: return DrawTargetSkia::GetMaxSurfaceSize(); #ifdef WIN32 case BackendType::DIRECT2D1_1: return DrawTargetD2D1::GetMaxSurfaceSize(); #endif default: return 0;
}
}
already_AddRefed<NativeFontResource> Factory::CreateNativeFontResource(
uint8_t* aData, uint32_t aSize, FontType aFontType, void* aFontContext) { switch (aFontType) { #ifdef WIN32 case FontType::DWRITE: return NativeFontResourceDWrite::Create(aData, aSize); case FontType::GDI: return NativeFontResourceGDI::Create(aData, aSize); #elifdefined(XP_DARWIN) case FontType::MAC: return NativeFontResourceMac::Create(aData, aSize); #elifdefined(MOZ_WIDGET_GTK) case FontType::FONTCONFIG: return NativeFontResourceFontconfig::Create(
aData, aSize, static_cast<FT_Library>(aFontContext)); #elifdefined(MOZ_WIDGET_ANDROID) case FontType::FREETYPE: return NativeFontResourceFreeType::Create(
aData, aSize, static_cast<FT_Library>(aFontContext)); #endif default:
gfxWarning()
<< "Unable to create requested font resource from truetype data"; return nullptr;
}
}
already_AddRefed<UnscaledFont> Factory::CreateUnscaledFontFromFontDescriptor(
FontType aType, const uint8_t* aData, uint32_t aDataLength,
uint32_t aIndex) { switch (aType) { #ifdef WIN32 case FontType::DWRITE: return UnscaledFontDWrite::CreateFromFontDescriptor(aData, aDataLength,
aIndex); case FontType::GDI: return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength,
aIndex); #elifdefined(XP_DARWIN) case FontType::MAC: return UnscaledFontMac::CreateFromFontDescriptor(aData, aDataLength,
aIndex); #elifdefined(MOZ_WIDGET_GTK) case FontType::FONTCONFIG: return UnscaledFontFontconfig::CreateFromFontDescriptor(
aData, aDataLength, aIndex); #elifdefined(MOZ_WIDGET_ANDROID) case FontType::FREETYPE: return UnscaledFontFreeType::CreateFromFontDescriptor(aData, aDataLength,
aIndex); #endif default:
gfxWarning() << "Invalid type specified for UnscaledFont font descriptor"; return nullptr;
}
}
already_AddRefed<SharedFTFace> Factory::NewSharedFTFace(FT_Library aFTLibrary, constchar* aFilename, int aFaceIndex) {
FT_Face face = NewFTFace(aFTLibrary, aFilename, aFaceIndex); if (!face) { return nullptr;
}
RefPtr<FTUserFontData> data; # ifdef ANDROID // If the font has variations, we may later need to "clone" it in // UnscaledFontFreeType::CreateScaledFont. To support this, we attach an // FTUserFontData that records the filename used to instantiate the face. if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
data = new FTUserFontData(aFilename);
} # endif return MakeAndAddRef<SharedFTFace>(face, data);
}
AutoSerializeWithMoz2D::AutoSerializeWithMoz2D(BackendType aBackendType) { #ifdef WIN32 // We use a multi-threaded ID2D1Factory1, so that makes the calls through the // Direct2D API thread-safe. However, if the Moz2D objects are using Direct3D // resources we need to make sure that calls through the Direct3D or DXGI API // use the Direct2D synchronization. It's possible that this should be pushed // down into the TextureD3D11 objects, so that we always use this. if (aBackendType == BackendType::DIRECT2D1_1 ||
aBackendType == BackendType::DIRECT2D) { auto factory = D2DFactory(); if (factory) {
factory->QueryInterface( static_cast<ID2D1Multithread**>(getter_AddRefs(mMT))); if (mMT) {
mMT->Enter();
}
}
} #endif
}
if (mDWriteSystemFonts && !aUpdate) { return mDWriteSystemFonts;
}
if (!mDWriteFactory) { if ((rand() & 0x3f) == 0) {
gfxCriticalError(int(gfx::LogOptions::AssertOnCall))
<< "Failed to create DWrite factory";
} else {
gfxWarning() << "Failed to create DWrite factory";
}
return nullptr;
}
RefPtr<IDWriteFontCollection> systemFonts;
HRESULT hr =
mDWriteFactory->GetSystemFontCollection(getter_AddRefs(systemFonts)); if (FAILED(hr) || !systemFonts) { // only crash some of the time so those experiencing this problem // don't stop using Firefox if ((rand() & 0x3f) == 0) {
gfxCriticalError(int(gfx::LogOptions::AssertOnCall))
<< "Failed to create DWrite system font collection";
} else {
gfxWarning() << "Failed to create DWrite system font collection";
} return nullptr;
}
mDWriteSystemFonts = systemFonts;
already_AddRefed<DataSourceSurface> Factory::CreateWrappingDataSourceSurface(
uint8_t* aData, int32_t aStride, const IntSize& aSize,
SurfaceFormat aFormat,
SourceSurfaceDeallocator aDeallocator /* = nullptr */, void* aClosure /* = nullptr */) { // Just check for negative/zero size instead of the full AllowedSurfaceSize() // - since the data is already allocated we do not need to check for a // possible overflow - it already worked. if (aSize.width <= 0 || aSize.height <= 0) { return nullptr;
} if (!aDeallocator && aClosure) { return nullptr;
}
// Special case: If the source and destination have different formats and the // destination is B8G8R8A8 then convert the source to B8G8R8A8 and readback. if ((srcDesc.Format != DXGIFormat(mappedData.format)) &&
(mappedData.format == SurfaceFormat::B8G8R8A8)) { return ConvertSourceAndRetryReadback(aDestCpuTexture, aSrcTexture);
}
if ((IntSize(srcDesc.Width, srcDesc.Height) != mappedData.size) ||
(srcDesc.Format != DXGIFormat(mappedData.format))) {
gfxWarning() << "Attempted readback between incompatible textures"; returnfalse;
}
// Special case: If the source and destination have different formats and the // destination is B8G8R8A8 then convert the source to B8G8R8A8 and readback. if ((srcDesc.Format != DXGIFormat(aDestCpuTexture->GetFormat())) &&
(aDestCpuTexture->GetFormat() == SurfaceFormat::B8G8R8A8)) { return ConvertSourceAndRetryReadback(aDestCpuTexture, aSrcTexture,
aArrayIndex);
}
if ((IntSize(srcDesc.Width, srcDesc.Height) != aDestCpuTexture->GetSize()) ||
(srcDesc.Format != DXGIFormat(aDestCpuTexture->GetFormat()))) {
gfxWarning() << "Attempted readback between incompatible textures"; returnfalse;
}
gfx::DataSourceSurface::MappedSurface mappedSurface; if (!aDestCpuTexture->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) { returnfalse;
}
MOZ_ASSERT(aArrayIndex == 0);
bool ret =
ReadbackTexture(mappedSurface.mData, mappedSurface.mStride, aSrcTexture);
aDestCpuTexture->Unmap(); return ret;
}
RefPtr<ID3D11Device> device;
aSrcTexture->GetDevice(getter_AddRefs(device)); if (!device) {
gfxWarning() << "Failed to get D3D11 device from source texture"; returnfalse;
}
RefPtr<ID3D11DeviceContext> context;
device->GetImmediateContext(getter_AddRefs(context)); if (!context) {
gfxWarning() << "Could not get an immediate D3D11 context"; returnfalse;
}
RefPtr<IDXGIKeyedMutex> mutex;
HRESULT hr = aSrcTexture->QueryInterface(__uuidof(IDXGIKeyedMutex),
(void**)getter_AddRefs(mutex)); if (SUCCEEDED(hr) && mutex) {
hr = mutex->AcquireSync(0, 2000); if (hr != S_OK) {
gfxWarning() << "Could not acquire DXGI surface lock in 2 seconds"; returnfalse;
}
}
void CriticalLogger::CrashAction(LogReason aReason) { if (Factory::GetLogForwarder()) {
Factory::GetLogForwarder()->CrashAction(aReason);
}
}
#ifdef WIN32 void LogWStr(constwchar_t* aWStr, std::stringstream& aOut) { int n =
WideCharToMultiByte(CP_ACP, 0, aWStr, -1, nullptr, 0, nullptr, nullptr); if (n > 1) {
std::vector<char> str(n);
WideCharToMultiByte(CP_ACP, 0, aWStr, -1, str.data(), n, nullptr, nullptr);
aOut << str.data();
}
} #endif
} // namespace mozilla::gfx
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.32Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.