2011-06-24 21:41:16 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2012-05-21 15:12:37 +04:00
|
|
|
* 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/. */
|
2011-06-24 21:41:16 +04:00
|
|
|
|
|
|
|
#include "2D.h"
|
|
|
|
|
|
|
|
#ifdef USE_CAIRO
|
|
|
|
#include "DrawTargetCairo.h"
|
2013-06-05 21:48:59 +04:00
|
|
|
#include "ScaledFontCairo.h"
|
2011-06-24 21:41:16 +04:00
|
|
|
#endif
|
|
|
|
|
2011-11-02 23:55:03 +04:00
|
|
|
#ifdef USE_SKIA
|
|
|
|
#include "DrawTargetSkia.h"
|
2012-01-09 22:54:44 +04:00
|
|
|
#include "ScaledFontBase.h"
|
2012-05-17 02:30:10 +04:00
|
|
|
#ifdef MOZ_ENABLE_FREETYPE
|
2013-06-05 21:48:59 +04:00
|
|
|
#define USE_SKIA_FREETYPE
|
|
|
|
#include "ScaledFontCairo.h"
|
2011-11-02 23:55:03 +04:00
|
|
|
#endif
|
2012-05-17 02:30:10 +04:00
|
|
|
#endif
|
2012-01-09 22:54:44 +04:00
|
|
|
|
2014-05-03 12:13:00 +04:00
|
|
|
#if defined(WIN32)
|
2011-11-18 08:00:37 +04:00
|
|
|
#include "ScaledFontWin.h"
|
|
|
|
#endif
|
2012-01-09 22:54:44 +04:00
|
|
|
|
2015-06-12 15:48:42 +03:00
|
|
|
#ifdef XP_DARWIN
|
2012-01-09 22:54:44 +04:00
|
|
|
#include "ScaledFontMac.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2015-06-12 15:48:42 +03:00
|
|
|
#ifdef XP_DARWIN
|
2012-01-09 22:54:44 +04:00
|
|
|
#include "DrawTargetCG.h"
|
2011-11-02 23:55:03 +04:00
|
|
|
#endif
|
|
|
|
|
2011-06-24 21:41:16 +04:00
|
|
|
#ifdef WIN32
|
|
|
|
#include "DrawTargetD2D.h"
|
2013-07-17 16:12:22 +04:00
|
|
|
#include "DrawTargetD2D1.h"
|
2011-06-24 21:41:16 +04:00
|
|
|
#include "ScaledFontDWrite.h"
|
|
|
|
#include <d3d10_1.h>
|
2013-07-17 16:12:22 +04:00
|
|
|
#include "HelpersD2D.h"
|
2011-06-24 21:41:16 +04:00
|
|
|
#endif
|
|
|
|
|
2012-04-04 00:25:52 +04:00
|
|
|
#include "DrawTargetDual.h"
|
2014-06-11 23:53:02 +04:00
|
|
|
#include "DrawTargetTiled.h"
|
2012-09-24 19:02:50 +04:00
|
|
|
#include "DrawTargetRecording.h"
|
2011-11-02 23:55:03 +04:00
|
|
|
|
2012-05-21 19:27:30 +04:00
|
|
|
#include "SourceSurfaceRawData.h"
|
|
|
|
|
2012-09-24 19:02:50 +04:00
|
|
|
#include "DrawEventRecorder.h"
|
|
|
|
|
2016-01-05 13:08:58 +03:00
|
|
|
#include "Preferences.h"
|
2011-06-24 21:41:16 +04:00
|
|
|
#include "Logging.h"
|
|
|
|
|
2014-01-17 14:06:17 +04:00
|
|
|
#include "mozilla/CheckedInt.h"
|
|
|
|
|
2015-10-30 01:48:20 +03:00
|
|
|
#if defined(MOZ_LOGGING)
|
|
|
|
GFX2D_API mozilla::LogModule*
|
2012-10-30 03:32:10 +04:00
|
|
|
GetGFX2DLog()
|
|
|
|
{
|
2015-10-30 01:48:20 +03:00
|
|
|
static mozilla::LazyLogModule sLog("gfx2d");
|
2012-10-30 03:32:10 +04:00
|
|
|
return sLog;
|
|
|
|
}
|
2015-09-22 18:39:12 +03:00
|
|
|
#endif
|
2011-06-24 21:41:16 +04:00
|
|
|
|
2012-05-10 08:31:14 +04:00
|
|
|
// 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
|
|
|
|
|
2013-11-09 03:00:21 +04:00
|
|
|
#if !(defined(__SSE2__) || defined(_M_X64) || \
|
|
|
|
(defined(_M_IX86_FP) && _M_IX86_FP >= 2))
|
2012-05-10 08:31:14 +04:00
|
|
|
// cpuid.h is available on gcc 4.3 and higher on i386 and x86_64
|
|
|
|
#include <cpuid.h>
|
|
|
|
|
2013-02-17 12:45:10 +04:00
|
|
|
static inline bool
|
2012-05-10 08:31:14 +04:00
|
|
|
HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit)
|
|
|
|
{
|
|
|
|
unsigned int regs[4];
|
|
|
|
return __get_cpuid(level, ®s[0], ®s[1], ®s[2], ®s[3]) &&
|
|
|
|
(regs[reg] & bit);
|
|
|
|
}
|
2013-11-09 03:00:21 +04:00
|
|
|
#endif
|
2012-05-10 08:31:14 +04:00
|
|
|
|
|
|
|
#define HAVE_CPU_DETECTION
|
|
|
|
#else
|
|
|
|
|
2012-05-16 12:40:51 +04:00
|
|
|
#if defined(_MSC_VER) && _MSC_VER >= 1600 && (defined(_M_IX86) || defined(_M_AMD64))
|
|
|
|
// MSVC 2005 or later supports __cpuid by intrin.h
|
|
|
|
// But it does't work on MSVC 2005 with SDK 7.1 (Bug 753772)
|
2012-05-10 08:31:14 +04:00
|
|
|
#include <intrin.h>
|
|
|
|
|
|
|
|
#define HAVE_CPU_DETECTION
|
|
|
|
#elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__))
|
|
|
|
|
|
|
|
// Define a function identical to MSVC function.
|
|
|
|
#ifdef __i386
|
|
|
|
static void
|
|
|
|
__cpuid(int CPUInfo[4], int InfoType)
|
|
|
|
{
|
|
|
|
asm (
|
|
|
|
"xchg %esi, %ebx\n"
|
|
|
|
"cpuid\n"
|
|
|
|
"movl %eax, (%edi)\n"
|
|
|
|
"movl %ebx, 4(%edi)\n"
|
|
|
|
"movl %ecx, 8(%edi)\n"
|
|
|
|
"movl %edx, 12(%edi)\n"
|
|
|
|
"xchg %esi, %ebx\n"
|
|
|
|
:
|
|
|
|
: "a"(InfoType), // %eax
|
|
|
|
"D"(CPUInfo) // %edi
|
|
|
|
: "%ecx", "%edx", "%esi"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static void
|
|
|
|
__cpuid(int CPUInfo[4], int InfoType)
|
|
|
|
{
|
|
|
|
asm (
|
|
|
|
"xchg %rsi, %rbx\n"
|
|
|
|
"cpuid\n"
|
|
|
|
"movl %eax, (%rdi)\n"
|
|
|
|
"movl %ebx, 4(%rdi)\n"
|
|
|
|
"movl %ecx, 8(%rdi)\n"
|
|
|
|
"movl %edx, 12(%rdi)\n"
|
|
|
|
"xchg %rsi, %rbx\n"
|
|
|
|
:
|
|
|
|
: "a"(InfoType), // %eax
|
|
|
|
"D"(CPUInfo) // %rdi
|
|
|
|
: "%ecx", "%edx", "%rsi"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define HAVE_CPU_DETECTION
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_CPU_DETECTION
|
2013-02-17 12:45:10 +04:00
|
|
|
static inline bool
|
2012-05-10 08:31:14 +04:00
|
|
|
HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit)
|
|
|
|
{
|
|
|
|
// Check that the level in question is supported.
|
|
|
|
volatile int regs[4];
|
|
|
|
__cpuid((int *)regs, level & 0x80000000u);
|
|
|
|
if (unsigned(regs[0]) < level)
|
|
|
|
return false;
|
|
|
|
__cpuid((int *)regs, level);
|
|
|
|
return !!(unsigned(regs[reg]) & bit);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2011-06-24 21:41:16 +04:00
|
|
|
namespace mozilla {
|
|
|
|
namespace gfx {
|
|
|
|
|
2016-01-05 13:08:58 +03:00
|
|
|
int32_t LoggingPrefs::sGfxLogLevel =
|
|
|
|
PreferenceAccess::RegisterLivePref("gfx.logging.level", &sGfxLogLevel,
|
|
|
|
LOG_DEFAULT);
|
2011-06-24 21:41:16 +04:00
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
ID3D10Device1 *Factory::mD3D10Device;
|
2013-07-17 16:12:22 +04:00
|
|
|
ID3D11Device *Factory::mD3D11Device;
|
|
|
|
ID2D1Device *Factory::mD2D1Device;
|
|
|
|
#endif
|
2011-06-24 21:41:16 +04:00
|
|
|
|
2012-09-24 19:02:50 +04:00
|
|
|
DrawEventRecorder *Factory::mRecorder;
|
|
|
|
|
2015-11-18 18:59:11 +03:00
|
|
|
mozilla::gfx::Config* Factory::sConfig = nullptr;
|
|
|
|
|
|
|
|
void
|
|
|
|
Factory::Init(const Config& aConfig)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!sConfig);
|
|
|
|
sConfig = new Config(aConfig);
|
|
|
|
|
|
|
|
// Make sure we don't completely break rendering because of a typo in the
|
|
|
|
// pref or whatnot.
|
|
|
|
const int32_t kMinAllocPref = 10000000;
|
|
|
|
const int32_t kMinSizePref = 2048;
|
|
|
|
if (sConfig->mMaxAllocSize < kMinAllocPref) {
|
|
|
|
sConfig->mMaxAllocSize = kMinAllocPref;
|
|
|
|
}
|
|
|
|
if (sConfig->mMaxTextureSize < kMinSizePref) {
|
|
|
|
sConfig->mMaxTextureSize = kMinSizePref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Factory::ShutDown()
|
|
|
|
{
|
|
|
|
if (sConfig) {
|
|
|
|
delete sConfig;
|
|
|
|
sConfig = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-10 08:31:14 +04:00
|
|
|
bool
|
|
|
|
Factory::HasSSE2()
|
|
|
|
{
|
2012-05-16 12:40:51 +04:00
|
|
|
#if defined(__SSE2__) || defined(_M_X64) || \
|
|
|
|
(defined(_M_IX86_FP) && _M_IX86_FP >= 2)
|
|
|
|
// gcc with -msse2 (default on OSX and x86-64)
|
|
|
|
// cl.exe with -arch:SSE2 (default on x64 compiler)
|
2012-05-10 08:31:14 +04:00
|
|
|
return true;
|
2012-05-16 12:40:51 +04:00
|
|
|
#elif defined(HAVE_CPU_DETECTION)
|
2014-09-06 08:16:06 +04:00
|
|
|
static enum {
|
|
|
|
UNINITIALIZED,
|
|
|
|
NO_SSE2,
|
|
|
|
HAS_SSE2
|
|
|
|
} sDetectionState = UNINITIALIZED;
|
|
|
|
|
|
|
|
if (sDetectionState == UNINITIALIZED) {
|
|
|
|
sDetectionState = HasCPUIDBit(1u, edx, (1u<<26)) ? HAS_SSE2 : NO_SSE2;
|
|
|
|
}
|
|
|
|
return sDetectionState == HAS_SSE2;
|
2012-05-10 08:31:14 +04:00
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-12-18 01:54:04 +03:00
|
|
|
// If the size is "reasonable", we want gfxCriticalError to assert, so
|
|
|
|
// this is the option set up for it.
|
|
|
|
inline int LoggerOptionsBasedOnSize(const IntSize& aSize)
|
|
|
|
{
|
|
|
|
return CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Factory::ReasonableSurfaceSize(const IntSize &aSize)
|
|
|
|
{
|
2015-11-18 18:59:11 +03:00
|
|
|
return Factory::CheckSurfaceSize(aSize, 8192);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Factory::AllowedSurfaceSize(const IntSize &aSize)
|
|
|
|
{
|
|
|
|
if (sConfig) {
|
|
|
|
return Factory::CheckSurfaceSize(aSize,
|
|
|
|
sConfig->mMaxTextureSize,
|
|
|
|
sConfig->mMaxAllocSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CheckSurfaceSize(aSize);
|
2014-12-18 01:54:04 +03:00
|
|
|
}
|
|
|
|
|
2015-12-16 21:50:58 +03:00
|
|
|
bool
|
|
|
|
Factory::CheckBufferSize(int32_t bufSize)
|
|
|
|
{
|
|
|
|
return !sConfig || bufSize < sConfig->mMaxAllocSize;
|
|
|
|
}
|
|
|
|
|
2014-01-17 14:06:17 +04:00
|
|
|
bool
|
2015-11-18 18:59:11 +03:00
|
|
|
Factory::CheckSurfaceSize(const IntSize &sz,
|
|
|
|
int32_t extentLimit,
|
|
|
|
int32_t allocLimit)
|
2014-01-17 14:06:17 +04:00
|
|
|
{
|
2014-12-18 01:54:04 +03:00
|
|
|
if (sz.width <= 0 || sz.height <= 0) {
|
|
|
|
gfxDebug() << "Surface width or height <= 0!";
|
2014-01-17 14:06:17 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// reject images with sides bigger than limit
|
2015-11-18 18:59:11 +03:00
|
|
|
if (extentLimit && (sz.width > extentLimit || sz.height > extentLimit)) {
|
|
|
|
gfxDebug() << "Surface size too large (exceeds extent limit)!";
|
2014-01-17 14:06:17 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure the surface area doesn't overflow a int32_t
|
|
|
|
CheckedInt<int32_t> tmp = sz.width;
|
|
|
|
tmp *= sz.height;
|
|
|
|
if (!tmp.isValid()) {
|
|
|
|
gfxDebug() << "Surface size too large (would overflow)!";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// assuming 4 bytes per pixel, make sure the allocation size
|
|
|
|
// doesn't overflow a int32_t either
|
|
|
|
CheckedInt<int32_t> stride = sz.width;
|
|
|
|
stride *= 4;
|
|
|
|
|
|
|
|
// When aligning the stride to 16 bytes, it can grow by up to 15 bytes.
|
|
|
|
stride += 16 - 1;
|
|
|
|
|
|
|
|
if (!stride.isValid()) {
|
|
|
|
gfxDebug() << "Surface size too large (stride overflows int32_t)!";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckedInt<int32_t> numBytes = GetAlignedStride<16>(sz.width * 4);
|
|
|
|
numBytes *= sz.height;
|
|
|
|
if (!numBytes.isValid()) {
|
|
|
|
gfxDebug() << "Surface size too large (allocation size would overflow int32_t)!";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-18 18:59:11 +03:00
|
|
|
if (allocLimit && allocLimit < numBytes.value()) {
|
|
|
|
gfxDebug() << "Surface size too large (exceeds allocation limit)!";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-01-17 14:06:17 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2011-06-24 21:41:16 +04:00
|
|
|
Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat)
|
|
|
|
{
|
2015-11-18 18:59:11 +03:00
|
|
|
if (!AllowedSurfaceSize(aSize)) {
|
2015-12-29 22:03:58 +03:00
|
|
|
gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (CDT) " << aSize;
|
2014-01-17 14:06:17 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> retVal;
|
2011-06-24 21:41:16 +04:00
|
|
|
switch (aBackend) {
|
|
|
|
#ifdef WIN32
|
2014-01-10 23:06:16 +04:00
|
|
|
case BackendType::DIRECT2D:
|
2011-06-24 21:41:16 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetD2D> newTarget;
|
2011-06-24 21:41:16 +04:00
|
|
|
newTarget = new DrawTargetD2D();
|
|
|
|
if (newTarget->Init(aSize, aFormat)) {
|
2012-09-24 19:02:50 +04:00
|
|
|
retVal = newTarget;
|
2011-06-24 21:41:16 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2014-01-10 23:06:16 +04:00
|
|
|
case BackendType::DIRECT2D1_1:
|
2013-07-17 16:12:22 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetD2D1> newTarget;
|
2013-07-17 16:12:22 +04:00
|
|
|
newTarget = new DrawTargetD2D1();
|
|
|
|
if (newTarget->Init(aSize, aFormat)) {
|
|
|
|
retVal = newTarget;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2015-06-12 15:48:42 +03:00
|
|
|
#elif defined XP_DARWIN
|
2014-01-10 23:06:16 +04:00
|
|
|
case BackendType::COREGRAPHICS:
|
|
|
|
case BackendType::COREGRAPHICS_ACCELERATED:
|
2011-11-02 23:55:03 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetCG> newTarget;
|
2012-04-13 06:10:22 +04:00
|
|
|
newTarget = new DrawTargetCG();
|
2012-07-31 19:17:43 +04:00
|
|
|
if (newTarget->Init(aBackend, aSize, aFormat)) {
|
2012-09-24 19:02:50 +04:00
|
|
|
retVal = newTarget;
|
2011-11-02 23:55:03 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-01-09 22:54:44 +04:00
|
|
|
#endif
|
2012-04-13 06:10:22 +04:00
|
|
|
#ifdef USE_SKIA
|
2014-01-10 23:06:16 +04:00
|
|
|
case BackendType::SKIA:
|
2012-01-09 22:54:44 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetSkia> newTarget;
|
2012-04-13 06:10:22 +04:00
|
|
|
newTarget = new DrawTargetSkia();
|
2012-01-09 22:54:44 +04:00
|
|
|
if (newTarget->Init(aSize, aFormat)) {
|
2012-09-24 19:02:50 +04:00
|
|
|
retVal = newTarget;
|
2012-01-09 22:54:44 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2013-11-04 03:57:36 +04:00
|
|
|
#endif
|
|
|
|
#ifdef USE_CAIRO
|
2014-01-10 23:06:16 +04:00
|
|
|
case BackendType::CAIRO:
|
2013-11-04 03:57:36 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetCairo> newTarget;
|
2013-11-04 03:57:36 +04:00
|
|
|
newTarget = new DrawTargetCairo();
|
|
|
|
if (newTarget->Init(aSize, aFormat)) {
|
|
|
|
retVal = newTarget;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-06-24 21:41:16 +04:00
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
gfxDebug() << "Invalid draw target type specified.";
|
2012-08-14 22:06:12 +04:00
|
|
|
return nullptr;
|
2011-06-24 21:41:16 +04:00
|
|
|
}
|
|
|
|
|
2012-09-24 19:02:50 +04:00
|
|
|
if (mRecorder && retVal) {
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<DrawTargetRecording>(mRecorder, retVal);
|
2012-09-24 19:02:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!retVal) {
|
|
|
|
// Failed
|
2014-12-18 01:54:04 +03:00
|
|
|
gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize;
|
2012-09-24 19:02:50 +04:00
|
|
|
}
|
2014-12-18 01:54:04 +03:00
|
|
|
|
2014-06-13 20:09:23 +04:00
|
|
|
return retVal.forget();
|
2012-09-24 19:02:50 +04:00
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2012-09-24 19:02:50 +04:00
|
|
|
Factory::CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT)
|
|
|
|
{
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<DrawTargetRecording>(aRecorder, aDT);
|
2011-06-24 21:41:16 +04:00
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2014-12-18 01:54:04 +03:00
|
|
|
Factory::CreateDrawTargetForData(BackendType aBackend,
|
|
|
|
unsigned char *aData,
|
|
|
|
const IntSize &aSize,
|
|
|
|
int32_t aStride,
|
2012-04-02 23:15:08 +04:00
|
|
|
SurfaceFormat aFormat)
|
|
|
|
{
|
2014-11-20 17:48:07 +03:00
|
|
|
MOZ_ASSERT(aData);
|
2015-11-18 18:59:11 +03:00
|
|
|
if (!AllowedSurfaceSize(aSize)) {
|
2015-12-29 22:03:58 +03:00
|
|
|
gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (DTD) " << aSize;
|
2014-01-17 14:06:17 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> retVal;
|
2012-09-24 19:02:50 +04:00
|
|
|
|
2012-04-02 23:15:08 +04:00
|
|
|
switch (aBackend) {
|
|
|
|
#ifdef USE_SKIA
|
2014-01-10 23:06:16 +04:00
|
|
|
case BackendType::SKIA:
|
2012-04-02 23:15:08 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetSkia> newTarget;
|
2012-04-02 23:15:08 +04:00
|
|
|
newTarget = new DrawTargetSkia();
|
|
|
|
newTarget->Init(aData, aSize, aStride, aFormat);
|
2012-09-24 19:02:50 +04:00
|
|
|
retVal = newTarget;
|
2014-02-19 20:37:26 +04:00
|
|
|
break;
|
2012-04-02 23:15:08 +04:00
|
|
|
}
|
2012-07-26 22:06:23 +04:00
|
|
|
#endif
|
2015-06-12 15:48:42 +03:00
|
|
|
#ifdef XP_DARWIN
|
2014-01-10 23:06:16 +04:00
|
|
|
case BackendType::COREGRAPHICS:
|
2012-07-26 22:06:23 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
|
2012-07-31 19:17:43 +04:00
|
|
|
if (newTarget->Init(aBackend, aData, aSize, aStride, aFormat))
|
2014-06-13 20:09:23 +04:00
|
|
|
return newTarget.forget();
|
2012-07-26 22:06:23 +04:00
|
|
|
break;
|
|
|
|
}
|
2013-11-04 03:57:36 +04:00
|
|
|
#endif
|
|
|
|
#ifdef USE_CAIRO
|
2014-01-10 23:06:16 +04:00
|
|
|
case BackendType::CAIRO:
|
2013-11-04 03:57:36 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetCairo> newTarget;
|
2013-11-04 03:57:36 +04:00
|
|
|
newTarget = new DrawTargetCairo();
|
|
|
|
if (newTarget->Init(aData, aSize, aStride, aFormat)) {
|
2014-06-13 20:09:23 +04:00
|
|
|
retVal = newTarget.forget();
|
2013-11-04 03:57:36 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-04-02 23:15:08 +04:00
|
|
|
#endif
|
|
|
|
default:
|
2015-09-19 12:19:07 +03:00
|
|
|
gfxCriticalNote << "Invalid draw target type specified: " << (int)aBackend;
|
2012-08-14 22:06:12 +04:00
|
|
|
return nullptr;
|
2012-04-02 23:15:08 +04:00
|
|
|
}
|
|
|
|
|
2012-09-24 19:02:50 +04:00
|
|
|
if (mRecorder && retVal) {
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<DrawTargetRecording>(mRecorder, retVal, true);
|
2012-09-24 19:02:50 +04:00
|
|
|
}
|
|
|
|
|
2013-11-04 03:57:36 +04:00
|
|
|
if (!retVal) {
|
2015-09-19 12:19:07 +03:00
|
|
|
gfxCriticalNote << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize << ", Data: " << hexa(aData) << ", Stride: " << aStride;
|
2013-11-04 03:57:36 +04:00
|
|
|
}
|
|
|
|
|
2014-06-13 20:09:23 +04:00
|
|
|
return retVal.forget();
|
2012-04-02 23:15:08 +04:00
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2014-06-11 23:53:02 +04:00
|
|
|
Factory::CreateTiledDrawTarget(const TileSet& aTileSet)
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetTiled> dt = new DrawTargetTiled();
|
2014-06-11 23:53:02 +04:00
|
|
|
|
|
|
|
if (!dt->Init(aTileSet)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-06-13 20:09:23 +04:00
|
|
|
return dt.forget();
|
2014-06-11 23:53:02 +04:00
|
|
|
}
|
|
|
|
|
2015-01-08 00:58:20 +03:00
|
|
|
bool
|
|
|
|
Factory::DoesBackendSupportDataDrawtarget(BackendType aType)
|
|
|
|
{
|
|
|
|
switch (aType) {
|
|
|
|
case BackendType::DIRECT2D:
|
|
|
|
case BackendType::DIRECT2D1_1:
|
|
|
|
case BackendType::RECORDING:
|
|
|
|
case BackendType::NONE:
|
|
|
|
case BackendType::COREGRAPHICS_ACCELERATED:
|
|
|
|
return false;
|
|
|
|
case BackendType::CAIRO:
|
|
|
|
case BackendType::COREGRAPHICS:
|
|
|
|
case BackendType::SKIA:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-02-25 00:39:01 +03:00
|
|
|
uint32_t
|
|
|
|
Factory::GetMaxSurfaceSize(BackendType aType)
|
|
|
|
{
|
|
|
|
switch (aType) {
|
|
|
|
case BackendType::CAIRO:
|
|
|
|
case BackendType::COREGRAPHICS:
|
|
|
|
return DrawTargetCairo::GetMaxSurfaceSize();
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
case BackendType::COREGRAPHICS_ACCELERATED:
|
|
|
|
return DrawTargetCG::GetMaxSurfaceSize();
|
|
|
|
#endif
|
2015-11-26 06:21:40 +03:00
|
|
|
#ifdef USE_SKIA
|
2015-02-25 00:39:01 +03:00
|
|
|
case BackendType::SKIA:
|
2015-11-19 21:35:31 +03:00
|
|
|
return DrawTargetSkia::GetMaxSurfaceSize();
|
2015-11-26 06:21:40 +03:00
|
|
|
#endif
|
2015-02-25 00:39:01 +03:00
|
|
|
#ifdef WIN32
|
|
|
|
case BackendType::DIRECT2D:
|
|
|
|
return DrawTargetD2D::GetMaxSurfaceSize();
|
|
|
|
case BackendType::DIRECT2D1_1:
|
|
|
|
return DrawTargetD2D1::GetMaxSurfaceSize();
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<ScaledFont>
|
2011-06-24 21:41:16 +04:00
|
|
|
Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize)
|
|
|
|
{
|
|
|
|
switch (aNativeFont.mType) {
|
|
|
|
#ifdef WIN32
|
2014-01-10 23:06:16 +04:00
|
|
|
case NativeFontType::DWRITE_FONT_FACE:
|
2011-06-24 21:41:16 +04:00
|
|
|
{
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<ScaledFontDWrite>(static_cast<IDWriteFontFace*>(aNativeFont.mFont), aSize);
|
2011-06-24 21:41:16 +04:00
|
|
|
}
|
2012-09-24 19:02:50 +04:00
|
|
|
#if defined(USE_CAIRO) || defined(USE_SKIA)
|
2014-01-10 23:06:16 +04:00
|
|
|
case NativeFontType::GDI_FONT_FACE:
|
2012-07-24 14:18:38 +04:00
|
|
|
{
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<ScaledFontWin>(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
|
2012-07-24 14:18:38 +04:00
|
|
|
}
|
2011-11-02 23:55:03 +04:00
|
|
|
#endif
|
2012-09-11 17:51:39 +04:00
|
|
|
#endif
|
2015-06-12 15:48:42 +03:00
|
|
|
#ifdef XP_DARWIN
|
2014-01-10 23:06:16 +04:00
|
|
|
case NativeFontType::MAC_FONT_FACE:
|
2011-11-02 23:55:03 +04:00
|
|
|
{
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<ScaledFontMac>(static_cast<CGFontRef>(aNativeFont.mFont), aSize);
|
2011-11-02 23:55:03 +04:00
|
|
|
}
|
2011-11-18 08:00:37 +04:00
|
|
|
#endif
|
2013-06-05 21:48:59 +04:00
|
|
|
#if defined(USE_CAIRO) || defined(USE_SKIA_FREETYPE)
|
2014-01-10 23:06:16 +04:00
|
|
|
case NativeFontType::CAIRO_FONT_FACE:
|
2012-01-10 22:26:59 +04:00
|
|
|
{
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<ScaledFontCairo>(static_cast<cairo_scaled_font_t*>(aNativeFont.mFont), aSize);
|
2012-01-10 22:26:59 +04:00
|
|
|
}
|
2012-01-27 22:08:46 +04:00
|
|
|
#endif
|
2011-06-24 21:41:16 +04:00
|
|
|
default:
|
|
|
|
gfxWarning() << "Invalid native font type specified.";
|
2012-08-14 22:06:12 +04:00
|
|
|
return nullptr;
|
2011-06-24 21:41:16 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-22 00:47:33 +03:00
|
|
|
already_AddRefed<ScaledFont>
|
|
|
|
Factory::CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize,
|
|
|
|
uint32_t aFaceIndex, Float aGlyphSize,
|
|
|
|
FontType aType)
|
2012-09-24 19:02:49 +04:00
|
|
|
{
|
|
|
|
switch (aType) {
|
|
|
|
#ifdef WIN32
|
2014-01-10 23:06:16 +04:00
|
|
|
case FontType::DWRITE:
|
2012-09-24 19:02:49 +04:00
|
|
|
{
|
2015-12-22 00:47:33 +03:00
|
|
|
return MakeAndAddRef<ScaledFontDWrite>(aData, aSize, aFaceIndex, aGlyphSize);
|
2012-09-24 19:02:49 +04:00
|
|
|
}
|
|
|
|
#endif
|
2016-01-05 13:08:56 +03:00
|
|
|
case FontType::CAIRO:
|
|
|
|
{
|
|
|
|
RefPtr<ScaledFontBase> scaledFont;
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
if (DrawTargetD2D::GetDWriteFactory()) {
|
|
|
|
scaledFont = new ScaledFontDWrite(aData, aSize, aFaceIndex, aGlyphSize);
|
|
|
|
} else {
|
|
|
|
scaledFont = new ScaledFontWin(aData, aSize, aFaceIndex, aGlyphSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!scaledFont->PopulateCairoScaledFont()) {
|
|
|
|
gfxWarning() << "Unable to create cairo scaled font from truetype data";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
gfxWarning() << "Unable to create cairo scaled font from truetype data";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return scaledFont.forget();
|
|
|
|
}
|
2012-09-24 19:02:49 +04:00
|
|
|
default:
|
2015-12-22 00:47:33 +03:00
|
|
|
gfxWarning() << "Unable to create requested font type from truetype data";
|
2012-09-24 19:02:49 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<ScaledFont>
|
2012-01-27 22:08:46 +04:00
|
|
|
Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont)
|
|
|
|
{
|
|
|
|
#ifdef USE_CAIRO
|
|
|
|
// In theory, we could pull the NativeFont out of the cairo_scaled_font_t*,
|
|
|
|
// but that would require a lot of code that would be otherwise repeated in
|
|
|
|
// various backends.
|
|
|
|
// Therefore, we just reuse CreateScaledFontForNativeFont's implementation.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<ScaledFont> font = CreateScaledFontForNativeFont(aNativeFont, aSize);
|
2012-01-27 22:08:46 +04:00
|
|
|
static_cast<ScaledFontBase*>(font.get())->SetCairoScaledFont(aScaledFont);
|
2014-06-13 20:09:23 +04:00
|
|
|
return font.forget();
|
2012-01-27 22:08:46 +04:00
|
|
|
#else
|
2012-08-14 22:06:12 +04:00
|
|
|
return nullptr;
|
2012-01-27 22:08:46 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2013-07-10 05:02:41 +04:00
|
|
|
Factory::CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB)
|
|
|
|
{
|
2014-11-20 17:48:07 +03:00
|
|
|
MOZ_ASSERT(targetA && targetB);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> newTarget =
|
2013-07-10 05:02:41 +04:00
|
|
|
new DrawTargetDual(targetA, targetB);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> retVal = newTarget;
|
2013-07-10 05:02:41 +04:00
|
|
|
|
|
|
|
if (mRecorder) {
|
|
|
|
retVal = new DrawTargetRecording(mRecorder, retVal);
|
|
|
|
}
|
|
|
|
|
2014-06-13 20:09:23 +04:00
|
|
|
return retVal.forget();
|
2013-07-10 05:02:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-24 21:41:16 +04:00
|
|
|
#ifdef WIN32
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2011-06-24 21:41:16 +04:00
|
|
|
Factory::CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat)
|
|
|
|
{
|
2014-11-20 17:48:07 +03:00
|
|
|
MOZ_ASSERT(aTexture);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetD2D> newTarget;
|
2011-06-24 21:41:16 +04:00
|
|
|
|
|
|
|
newTarget = new DrawTargetD2D();
|
|
|
|
if (newTarget->Init(aTexture, aFormat)) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> retVal = newTarget;
|
2012-09-24 19:02:50 +04:00
|
|
|
|
|
|
|
if (mRecorder) {
|
2013-11-27 15:21:57 +04:00
|
|
|
retVal = new DrawTargetRecording(mRecorder, retVal, true);
|
2012-09-24 19:02:50 +04:00
|
|
|
}
|
|
|
|
|
2014-06-13 20:09:23 +04:00
|
|
|
return retVal.forget();
|
2011-06-24 21:41:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxWarning() << "Failed to create draw target for D3D10 texture.";
|
|
|
|
|
|
|
|
// Failed
|
2012-08-14 22:06:12 +04:00
|
|
|
return nullptr;
|
2011-06-24 21:41:16 +04:00
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2012-04-04 00:25:52 +04:00
|
|
|
Factory::CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
|
|
|
|
ID3D10Texture2D *aTextureB,
|
|
|
|
SurfaceFormat aFormat)
|
|
|
|
{
|
2014-11-20 17:48:07 +03:00
|
|
|
MOZ_ASSERT(aTextureA && aTextureB);
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetD2D> newTargetA;
|
|
|
|
RefPtr<DrawTargetD2D> newTargetB;
|
2012-04-04 00:25:52 +04:00
|
|
|
|
|
|
|
newTargetA = new DrawTargetD2D();
|
|
|
|
if (!newTargetA->Init(aTextureA, aFormat)) {
|
2015-01-20 20:47:29 +03:00
|
|
|
gfxWarning() << "Failed to create dual draw target for D3D10 texture.";
|
2012-08-14 22:06:12 +04:00
|
|
|
return nullptr;
|
2012-04-04 00:25:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
newTargetB = new DrawTargetD2D();
|
|
|
|
if (!newTargetB->Init(aTextureB, aFormat)) {
|
2015-01-20 20:47:29 +03:00
|
|
|
gfxWarning() << "Failed to create new draw target for D3D10 texture.";
|
2012-08-14 22:06:12 +04:00
|
|
|
return nullptr;
|
2012-04-04 00:25:52 +04:00
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> newTarget =
|
2012-04-04 00:25:52 +04:00
|
|
|
new DrawTargetDual(newTargetA, newTargetB);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> retVal = newTarget;
|
2012-09-24 19:02:50 +04:00
|
|
|
|
|
|
|
if (mRecorder) {
|
|
|
|
retVal = new DrawTargetRecording(mRecorder, retVal);
|
|
|
|
}
|
|
|
|
|
2014-06-13 20:09:23 +04:00
|
|
|
return retVal.forget();
|
2012-04-04 00:25:52 +04:00
|
|
|
}
|
|
|
|
|
2011-06-24 21:41:16 +04:00
|
|
|
void
|
|
|
|
Factory::SetDirect3D10Device(ID3D10Device1 *aDevice)
|
|
|
|
{
|
2014-06-17 21:00:13 +04:00
|
|
|
// 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?)
|
Refactor graphics device initialization on Windows. (bug 1183910 part 1, r=mattwoodrow,bas)
This patch addresses a number of inconsistencies in the device initialization process, as well as simplifying it for future use. All device decisions are now explicitly made up-front during startup, rather than implicitly or on-demand. In addition a number of restrictions have been placed on when we can construct devices.
Full change list:
(1) We no longer attempt to use D3D11 if acceleration is disabled or D3D9 is preferred. This is a departure from our previous behavior, where we would construct these devices but then not use them as a compositor backend.
(2) D3D11 startup no longer creates a content device (this is reserved for D2D initialization).
(3) D2D is only attempted if we managed to create a D3D11 compositor device. This is a departure from previous behavior where if D3D11 was not used for compositing, we could still create its machinery to use D2D as a content backend.
(4) D2D 1.1 initialization is now directly responsible for creating a D3D11 content device.
(5) D2D 1.0 and 1.1 logic have been disentangled for clarity.
(6) UpdateRenderMode() has been split up, so we can update backend prefs out of band with device resets.
(7) mUseGDIFonts and mUseDirectWrite have been removed as their state was confusing. Instead, D2D now depends on DWrite initialization succeeding. If later we fail to get a DWrite font list, we revert our decision to use Direct2D.
(8) Device resets now clear a little more state, including the devices set in Moz2D Factory.
(9) We no longer create a DWrite text analyzer as it was unused.
2015-07-29 02:52:54 +03:00
|
|
|
if (aDevice) {
|
|
|
|
aDevice->SetExceptionMode(0);
|
|
|
|
}
|
2011-06-24 21:41:16 +04:00
|
|
|
mD3D10Device = aDevice;
|
|
|
|
}
|
|
|
|
|
|
|
|
ID3D10Device1*
|
|
|
|
Factory::GetDirect3D10Device()
|
|
|
|
{
|
2014-06-17 21:00:13 +04:00
|
|
|
#ifdef DEBUG
|
2014-10-17 06:02:51 +04:00
|
|
|
if (mD3D10Device) {
|
|
|
|
UINT mode = mD3D10Device->GetExceptionMode();
|
|
|
|
MOZ_ASSERT(0 == mode);
|
|
|
|
}
|
2014-06-17 21:00:13 +04:00
|
|
|
#endif
|
2011-06-24 21:41:16 +04:00
|
|
|
return mD3D10Device;
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2014-09-15 01:51:27 +04:00
|
|
|
Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat)
|
|
|
|
{
|
2014-11-20 17:48:07 +03:00
|
|
|
MOZ_ASSERT(aTexture);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetD2D1> newTarget;
|
2014-09-15 01:51:27 +04:00
|
|
|
|
|
|
|
newTarget = new DrawTargetD2D1();
|
|
|
|
if (newTarget->Init(aTexture, aFormat)) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> retVal = newTarget;
|
2014-09-15 01:51:27 +04:00
|
|
|
|
|
|
|
if (mRecorder) {
|
|
|
|
retVal = new DrawTargetRecording(mRecorder, retVal, true);
|
|
|
|
}
|
|
|
|
|
2015-05-01 16:14:16 +03:00
|
|
|
return retVal.forget();
|
2014-09-15 01:51:27 +04:00
|
|
|
}
|
|
|
|
|
2015-01-20 20:47:29 +03:00
|
|
|
gfxWarning() << "Failed to create draw target for D3D11 texture.";
|
2014-09-15 01:51:27 +04:00
|
|
|
|
|
|
|
// Failed
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-07-17 16:12:22 +04:00
|
|
|
void
|
|
|
|
Factory::SetDirect3D11Device(ID3D11Device *aDevice)
|
|
|
|
{
|
|
|
|
mD3D11Device = aDevice;
|
|
|
|
|
2014-11-20 03:16:48 +03:00
|
|
|
if (mD2D1Device) {
|
|
|
|
mD2D1Device->Release();
|
|
|
|
mD2D1Device = nullptr;
|
|
|
|
}
|
|
|
|
|
2015-01-08 03:10:49 +03:00
|
|
|
if (!aDevice) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<ID2D1Factory1> factory = D2DFactory1();
|
2013-07-17 16:12:22 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDXGIDevice> device;
|
2015-10-18 07:40:10 +03:00
|
|
|
aDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(device));
|
2015-04-22 13:02:01 +03:00
|
|
|
HRESULT hr = factory->CreateDevice(device, &mD2D1Device);
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
gfxCriticalError() << "[D2D1] Failed to create gfx factory's D2D1 device, code: " << hexa(hr);
|
|
|
|
}
|
2013-07-17 16:12:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
ID3D11Device*
|
|
|
|
Factory::GetDirect3D11Device()
|
|
|
|
{
|
|
|
|
return mD3D11Device;
|
|
|
|
}
|
|
|
|
|
|
|
|
ID2D1Device*
|
|
|
|
Factory::GetD2D1Device()
|
|
|
|
{
|
|
|
|
return mD2D1Device;
|
|
|
|
}
|
2014-09-15 01:51:26 +04:00
|
|
|
|
|
|
|
bool
|
|
|
|
Factory::SupportsD2D1()
|
|
|
|
{
|
|
|
|
return !!D2DFactory1();
|
|
|
|
}
|
2013-07-17 16:12:22 +04:00
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<GlyphRenderingOptions>
|
2012-03-19 23:20:17 +04:00
|
|
|
Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams)
|
|
|
|
{
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<GlyphRenderingOptionsDWrite>(aParams);
|
2012-03-19 23:20:17 +04:00
|
|
|
}
|
|
|
|
|
2012-06-21 02:32:52 +04:00
|
|
|
uint64_t
|
|
|
|
Factory::GetD2DVRAMUsageDrawTarget()
|
|
|
|
{
|
|
|
|
return DrawTargetD2D::mVRAMUsageDT;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
Factory::GetD2DVRAMUsageSourceSurface()
|
|
|
|
{
|
|
|
|
return DrawTargetD2D::mVRAMUsageSS;
|
|
|
|
}
|
|
|
|
|
2012-11-25 23:00:31 +04:00
|
|
|
void
|
|
|
|
Factory::D2DCleanup()
|
|
|
|
{
|
2014-11-20 03:16:48 +03:00
|
|
|
if (mD2D1Device) {
|
|
|
|
mD2D1Device->Release();
|
|
|
|
mD2D1Device = nullptr;
|
|
|
|
}
|
|
|
|
DrawTargetD2D1::CleanupD2D();
|
2014-11-24 02:53:00 +03:00
|
|
|
DrawTargetD2D::CleanupD2D();
|
2012-11-25 23:00:31 +04:00
|
|
|
}
|
|
|
|
|
2011-06-24 21:41:16 +04:00
|
|
|
#endif // XP_WIN
|
|
|
|
|
2013-03-14 03:29:47 +04:00
|
|
|
#ifdef USE_SKIA_GPU
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2014-03-06 01:49:37 +04:00
|
|
|
Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext,
|
|
|
|
const IntSize &aSize,
|
|
|
|
SurfaceFormat aFormat)
|
2012-12-01 03:58:00 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> newTarget = new DrawTargetSkia();
|
2014-03-26 22:21:50 +04:00
|
|
|
if (!newTarget->InitWithGrContext(aGrContext, aSize, aFormat)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-06-13 20:09:23 +04:00
|
|
|
return newTarget.forget();
|
2012-12-01 03:58:00 +04:00
|
|
|
}
|
2013-10-22 23:15:24 +04:00
|
|
|
|
2013-03-14 03:29:47 +04:00
|
|
|
#endif // USE_SKIA_GPU
|
2012-12-01 03:58:00 +04:00
|
|
|
|
2013-11-01 17:52:06 +04:00
|
|
|
void
|
2013-12-05 08:52:03 +04:00
|
|
|
Factory::PurgeAllCaches()
|
2013-11-01 17:52:06 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-06-05 21:48:59 +04:00
|
|
|
#ifdef USE_SKIA_FREETYPE
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<GlyphRenderingOptions>
|
2015-09-02 21:12:32 +03:00
|
|
|
Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting, AntialiasMode aAntialiasMode)
|
2013-06-05 21:48:59 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<GlyphRenderingOptionsCairo> options =
|
2013-06-05 21:48:59 +04:00
|
|
|
new GlyphRenderingOptionsCairo();
|
|
|
|
|
|
|
|
options->SetHinting(aHinting);
|
|
|
|
options->SetAutoHinting(aAutoHinting);
|
2015-09-02 21:12:32 +03:00
|
|
|
options->SetAntialiasMode(aAntialiasMode);
|
2014-06-13 20:09:23 +04:00
|
|
|
return options.forget();
|
2013-06-05 21:48:59 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2014-04-15 07:46:31 +04:00
|
|
|
Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat)
|
2011-06-24 21:41:16 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> retVal;
|
2012-09-24 19:02:50 +04:00
|
|
|
|
2012-05-03 23:21:52 +04:00
|
|
|
#ifdef USE_CAIRO
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo();
|
2012-09-24 19:02:50 +04:00
|
|
|
|
2014-04-15 07:46:31 +04:00
|
|
|
if (newTarget->Init(aSurface, aSize, aFormat)) {
|
2012-09-24 19:02:50 +04:00
|
|
|
retVal = newTarget;
|
2011-06-24 21:41:16 +04:00
|
|
|
}
|
|
|
|
|
2012-09-24 19:02:50 +04:00
|
|
|
if (mRecorder && retVal) {
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<DrawTargetRecording>(mRecorder, retVal, true);
|
2012-09-24 19:02:50 +04:00
|
|
|
}
|
2012-05-03 23:21:52 +04:00
|
|
|
#endif
|
2014-06-13 20:09:23 +04:00
|
|
|
return retVal.forget();
|
2013-10-26 01:25:40 +04:00
|
|
|
}
|
|
|
|
|
2015-06-12 15:48:42 +03:00
|
|
|
#ifdef XP_DARWIN
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawTarget>
|
2013-07-10 05:02:41 +04:00
|
|
|
Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize)
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> retVal;
|
2013-07-10 05:02:41 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
|
2013-07-10 05:02:41 +04:00
|
|
|
|
|
|
|
if (newTarget->Init(cg, aSize)) {
|
|
|
|
retVal = newTarget;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mRecorder && retVal) {
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<DrawTargetRecording>(mRecorder, retVal);
|
2013-07-10 05:02:41 +04:00
|
|
|
}
|
2014-06-13 20:09:23 +04:00
|
|
|
return retVal.forget();
|
2013-07-10 05:02:41 +04:00
|
|
|
}
|
2014-10-24 20:32:23 +04:00
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<GlyphRenderingOptions>
|
2014-10-24 20:32:23 +04:00
|
|
|
Factory::CreateCGGlyphRenderingOptions(const Color &aFontSmoothingBackgroundColor)
|
|
|
|
{
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<GlyphRenderingOptionsCG>(aFontSmoothingBackgroundColor);
|
2014-10-24 20:32:23 +04:00
|
|
|
}
|
2013-07-10 05:02:41 +04:00
|
|
|
#endif
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DataSourceSurface>
|
2012-05-21 19:27:30 +04:00
|
|
|
Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
|
|
|
|
const IntSize &aSize,
|
|
|
|
SurfaceFormat aFormat)
|
|
|
|
{
|
2013-07-15 21:28:04 +04:00
|
|
|
if (aSize.width <= 0 || aSize.height <= 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2015-11-26 12:32:36 +03:00
|
|
|
MOZ_ASSERT(aData);
|
2013-07-15 21:28:04 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SourceSurfaceRawData> newSurf = new SourceSurfaceRawData();
|
2012-05-21 19:27:30 +04:00
|
|
|
|
2015-11-25 07:15:29 +03:00
|
|
|
newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false);
|
|
|
|
return newSurf.forget();
|
2012-05-21 19:27:30 +04:00
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DataSourceSurface>
|
2013-07-17 18:07:44 +04:00
|
|
|
Factory::CreateDataSourceSurface(const IntSize &aSize,
|
2014-09-11 01:54:16 +04:00
|
|
|
SurfaceFormat aFormat,
|
|
|
|
bool aZero)
|
2013-07-17 18:07:44 +04:00
|
|
|
{
|
2015-11-18 18:59:11 +03:00
|
|
|
if (!AllowedSurfaceSize(aSize)) {
|
2015-12-29 22:03:58 +03:00
|
|
|
gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (DSS) " << aSize;
|
2014-01-17 14:06:17 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
|
2014-09-11 01:54:16 +04:00
|
|
|
if (newSurf->Init(aSize, aFormat, aZero)) {
|
2014-06-13 20:09:23 +04:00
|
|
|
return newSurf.forget();
|
2013-07-17 18:07:44 +04:00
|
|
|
}
|
|
|
|
|
2014-08-27 19:57:43 +04:00
|
|
|
gfxWarning() << "CreateDataSourceSurface failed in init";
|
2013-07-17 18:07:44 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DataSourceSurface>
|
2013-12-19 19:31:07 +04:00
|
|
|
Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize,
|
|
|
|
SurfaceFormat aFormat,
|
2014-09-11 01:54:16 +04:00
|
|
|
int32_t aStride,
|
|
|
|
bool aZero)
|
2013-12-19 19:31:07 +04:00
|
|
|
{
|
|
|
|
if (aStride < aSize.width * BytesPerPixel(aFormat)) {
|
2014-12-18 01:54:04 +03:00
|
|
|
gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "CreateDataSourceSurfaceWithStride failed with bad stride " << aStride << ", " << aSize << ", " << aFormat;
|
2013-12-19 19:31:07 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
|
2014-09-11 01:54:16 +04:00
|
|
|
if (newSurf->InitWithStride(aSize, aFormat, aStride, aZero)) {
|
2014-06-13 20:09:23 +04:00
|
|
|
return newSurf.forget();
|
2013-12-19 19:31:07 +04:00
|
|
|
}
|
|
|
|
|
2014-12-18 01:54:04 +03:00
|
|
|
gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "CreateDataSourceSurfaceWithStride failed to initialize " << aSize << ", " << aFormat << ", " << aStride << ", " << aZero;
|
2013-12-19 19:31:07 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-12-18 09:52:16 +03:00
|
|
|
static uint16_t
|
|
|
|
PackRGB565(uint8_t r, uint8_t g, uint8_t b)
|
|
|
|
{
|
|
|
|
uint16_t pixel = ((r << 11) & 0xf800) |
|
|
|
|
((g << 5) & 0x07e0) |
|
|
|
|
((b ) & 0x001f);
|
|
|
|
|
|
|
|
return pixel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Factory::CopyDataSourceSurface(DataSourceSurface* aSource,
|
|
|
|
DataSourceSurface* aDest)
|
|
|
|
{
|
|
|
|
// Don't worry too much about speed.
|
|
|
|
MOZ_ASSERT(aSource->GetSize() == aDest->GetSize());
|
|
|
|
MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
|
|
|
|
aSource->GetFormat() == SurfaceFormat::R8G8B8X8 ||
|
|
|
|
aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
|
|
|
|
aSource->GetFormat() == SurfaceFormat::B8G8R8X8);
|
|
|
|
MOZ_ASSERT(aDest->GetFormat() == SurfaceFormat::R8G8B8A8 ||
|
|
|
|
aDest->GetFormat() == SurfaceFormat::R8G8B8X8 ||
|
|
|
|
aDest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
|
|
|
|
aDest->GetFormat() == SurfaceFormat::B8G8R8X8 ||
|
|
|
|
aDest->GetFormat() == SurfaceFormat::R5G6B5_UINT16);
|
|
|
|
|
|
|
|
const bool isSrcBGR = aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
|
|
|
|
aSource->GetFormat() == SurfaceFormat::B8G8R8X8;
|
|
|
|
const bool isDestBGR = aDest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
|
|
|
|
aDest->GetFormat() == SurfaceFormat::B8G8R8X8;
|
|
|
|
const bool needsSwap02 = isSrcBGR != isDestBGR;
|
|
|
|
|
|
|
|
const bool srcHasAlpha = aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
|
|
|
|
aSource->GetFormat() == SurfaceFormat::B8G8R8A8;
|
|
|
|
const bool destHasAlpha = aDest->GetFormat() == SurfaceFormat::R8G8B8A8 ||
|
|
|
|
aDest->GetFormat() == SurfaceFormat::B8G8R8A8;
|
|
|
|
const bool needsAlphaMask = !srcHasAlpha && destHasAlpha;
|
|
|
|
|
|
|
|
const bool needsConvertTo16Bits = aDest->GetFormat() == SurfaceFormat::R5G6B5_UINT16;
|
|
|
|
|
|
|
|
DataSourceSurface::MappedSurface srcMap;
|
|
|
|
DataSourceSurface::MappedSurface destMap;
|
|
|
|
if (!aSource->Map(DataSourceSurface::MapType::READ, &srcMap) ||
|
|
|
|
!aDest->Map(DataSourceSurface::MapType::WRITE, &destMap)) {
|
|
|
|
MOZ_ASSERT(false, "CopyDataSourceSurface: Failed to map surface.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(srcMap.mStride >= 0);
|
|
|
|
MOZ_ASSERT(destMap.mStride >= 0);
|
|
|
|
|
|
|
|
const size_t srcBPP = BytesPerPixel(aSource->GetFormat());
|
|
|
|
const size_t srcRowBytes = aSource->GetSize().width * srcBPP;
|
|
|
|
const size_t srcRowHole = srcMap.mStride - srcRowBytes;
|
|
|
|
|
|
|
|
const size_t destBPP = BytesPerPixel(aDest->GetFormat());
|
|
|
|
const size_t destRowBytes = aDest->GetSize().width * destBPP;
|
|
|
|
const size_t destRowHole = destMap.mStride - destRowBytes;
|
|
|
|
|
|
|
|
uint8_t* srcRow = srcMap.mData;
|
|
|
|
uint8_t* destRow = destMap.mData;
|
|
|
|
const size_t rows = aSource->GetSize().height;
|
|
|
|
for (size_t i = 0; i < rows; i++) {
|
|
|
|
const uint8_t* srcRowEnd = srcRow + srcRowBytes;
|
|
|
|
|
|
|
|
while (srcRow != srcRowEnd) {
|
|
|
|
uint8_t d0 = needsSwap02 ? srcRow[2] : srcRow[0];
|
|
|
|
uint8_t d1 = srcRow[1];
|
|
|
|
uint8_t d2 = needsSwap02 ? srcRow[0] : srcRow[2];
|
|
|
|
uint8_t d3 = needsAlphaMask ? 0xff : srcRow[3];
|
|
|
|
|
|
|
|
if (needsConvertTo16Bits) {
|
|
|
|
*(uint16_t*)destRow = PackRGB565(d0, d1, d2);
|
|
|
|
} else {
|
|
|
|
destRow[0] = d0;
|
|
|
|
destRow[1] = d1;
|
|
|
|
destRow[2] = d2;
|
|
|
|
destRow[3] = d3;
|
|
|
|
}
|
|
|
|
srcRow += srcBPP;
|
|
|
|
destRow += destBPP;
|
|
|
|
}
|
|
|
|
|
|
|
|
srcRow += srcRowHole;
|
|
|
|
destRow += destRowHole;
|
|
|
|
}
|
|
|
|
|
|
|
|
aSource->Unmap();
|
|
|
|
aDest->Unmap();
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<DrawEventRecorder>
|
2012-09-24 19:02:50 +04:00
|
|
|
Factory::CreateEventRecorderForFile(const char *aFilename)
|
|
|
|
{
|
2015-04-30 22:20:30 +03:00
|
|
|
return MakeAndAddRef<DrawEventRecorderFile>(aFilename);
|
2012-09-24 19:02:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Factory::SetGlobalEventRecorder(DrawEventRecorder *aRecorder)
|
|
|
|
{
|
|
|
|
mRecorder = aRecorder;
|
|
|
|
}
|
|
|
|
|
2014-09-18 01:23:02 +04:00
|
|
|
// static
|
|
|
|
void
|
|
|
|
Factory::SetLogForwarder(LogForwarder* aLogFwd) {
|
2015-11-18 18:59:11 +03:00
|
|
|
sConfig->mLogForwarder = aLogFwd;
|
2014-09-18 01:23:02 +04:00
|
|
|
}
|
|
|
|
|
2015-11-18 18:59:11 +03:00
|
|
|
|
2014-09-18 01:23:02 +04:00
|
|
|
// static
|
|
|
|
void
|
2014-10-24 21:54:26 +04:00
|
|
|
CriticalLogger::OutputMessage(const std::string &aString,
|
|
|
|
int aLevel, bool aNoNewline)
|
2014-09-18 01:23:02 +04:00
|
|
|
{
|
|
|
|
if (Factory::GetLogForwarder()) {
|
|
|
|
Factory::GetLogForwarder()->Log(aString);
|
|
|
|
}
|
|
|
|
|
2014-10-24 21:54:26 +04:00
|
|
|
BasicLogger::OutputMessage(aString, aLevel, aNoNewline);
|
2014-09-18 01:23:02 +04:00
|
|
|
}
|
|
|
|
|
2015-10-14 09:24:00 +03:00
|
|
|
void
|
|
|
|
CriticalLogger::CrashAction(LogReason aReason)
|
|
|
|
{
|
|
|
|
if (Factory::GetLogForwarder()) {
|
|
|
|
Factory::GetLogForwarder()->CrashAction(aReason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace gfx
|
|
|
|
} // namespace mozilla
|