LCOV - code coverage report
Current view: top level - gfx/2d - Factory.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 84 271 31.0 %
Date: 2017-07-14 16:53:18 Functions: 16 45 35.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "2D.h"
       7             : #include "Swizzle.h"
       8             : 
       9             : #ifdef USE_CAIRO
      10             : #include "DrawTargetCairo.h"
      11             : #include "ScaledFontCairo.h"
      12             : #include "SourceSurfaceCairo.h"
      13             : #endif
      14             : 
      15             : #ifdef USE_SKIA
      16             : #include "DrawTargetSkia.h"
      17             : #include "ScaledFontBase.h"
      18             : #ifdef MOZ_ENABLE_FREETYPE
      19             : #define USE_SKIA_FREETYPE
      20             : #include "ScaledFontCairo.h"
      21             : #endif
      22             : #endif
      23             : 
      24             : #if defined(WIN32)
      25             : #include "ScaledFontWin.h"
      26             : #include "NativeFontResourceGDI.h"
      27             : #include "UnscaledFontGDI.h"
      28             : #endif
      29             : 
      30             : #ifdef XP_DARWIN
      31             : #include "ScaledFontMac.h"
      32             : #include "NativeFontResourceMac.h"
      33             : #endif
      34             : 
      35             : #ifdef MOZ_WIDGET_GTK
      36             : #include "ScaledFontFontconfig.h"
      37             : #include "NativeFontResourceFontconfig.h"
      38             : #include "UnscaledFontFreeType.h"
      39             : #endif
      40             : 
      41             : #ifdef WIN32
      42             : #include "DrawTargetD2D1.h"
      43             : #include "ScaledFontDWrite.h"
      44             : #include "NativeFontResourceDWrite.h"
      45             : #include <d3d10_1.h>
      46             : #include "HelpersD2D.h"
      47             : #include "HelpersWinFonts.h"
      48             : #include "mozilla/Mutex.h"
      49             : #endif
      50             : 
      51             : #include "DrawTargetDual.h"
      52             : #include "DrawTargetTiled.h"
      53             : #include "DrawTargetWrapAndRecord.h"
      54             : #include "DrawTargetRecording.h"
      55             : 
      56             : #include "SourceSurfaceRawData.h"
      57             : 
      58             : #include "DrawEventRecorder.h"
      59             : 
      60             : #include "Logging.h"
      61             : 
      62             : #include "mozilla/CheckedInt.h"
      63             : 
      64             : #ifdef MOZ_ENABLE_FREETYPE
      65             : #include "ft2build.h"
      66             : #include FT_FREETYPE_H
      67             : 
      68             : #include "mozilla/Mutex.h"
      69             : #endif
      70             : 
      71             : #if defined(MOZ_LOGGING)
      72             : GFX2D_API mozilla::LogModule*
      73           1 : GetGFX2DLog()
      74             : {
      75             :   static mozilla::LazyLogModule sLog("gfx2d");
      76           1 :   return sLog;
      77             : }
      78             : #endif
      79             : 
      80             : // The following code was largely taken from xpcom/glue/SSE.cpp and
      81             : // made a little simpler.
      82             : enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 };
      83             : 
      84             : #ifdef HAVE_CPUID_H
      85             : 
      86             : #if !(defined(__SSE2__) || defined(_M_X64) || \
      87             :      (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
      88             : // cpuid.h is available on gcc 4.3 and higher on i386 and x86_64
      89             : #include <cpuid.h>
      90             : 
      91             : static inline bool
      92             : HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit)
      93             : {
      94             :   unsigned int regs[4];
      95             :   return __get_cpuid(level, &regs[0], &regs[1], &regs[2], &regs[3]) &&
      96             :          (regs[reg] & bit);
      97             : }
      98             : #endif
      99             : 
     100             : #define HAVE_CPU_DETECTION
     101             : #else
     102             : 
     103             : #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))
     104             : // MSVC 2005 or later supports __cpuid by intrin.h
     105             : #include <intrin.h>
     106             : 
     107             : #define HAVE_CPU_DETECTION
     108             : #elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__))
     109             : 
     110             : // Define a function identical to MSVC function.
     111             : #ifdef __i386
     112             : static void
     113             : __cpuid(int CPUInfo[4], int InfoType)
     114             : {
     115             :   asm (
     116             :     "xchg %esi, %ebx\n"
     117             :     "cpuid\n"
     118             :     "movl %eax, (%edi)\n"
     119             :     "movl %ebx, 4(%edi)\n"
     120             :     "movl %ecx, 8(%edi)\n"
     121             :     "movl %edx, 12(%edi)\n"
     122             :     "xchg %esi, %ebx\n"
     123             :     :
     124             :     : "a"(InfoType), // %eax
     125             :       "D"(CPUInfo) // %edi
     126             :     : "%ecx", "%edx", "%esi"
     127             :   );
     128             : }
     129             : #else
     130             : static void
     131             : __cpuid(int CPUInfo[4], int InfoType)
     132             : {
     133             :   asm (
     134             :     "xchg %rsi, %rbx\n"
     135             :     "cpuid\n"
     136             :     "movl %eax, (%rdi)\n"
     137             :     "movl %ebx, 4(%rdi)\n"
     138             :     "movl %ecx, 8(%rdi)\n"
     139             :     "movl %edx, 12(%rdi)\n"
     140             :     "xchg %rsi, %rbx\n"
     141             :     :
     142             :     : "a"(InfoType), // %eax
     143             :       "D"(CPUInfo) // %rdi
     144             :     : "%ecx", "%edx", "%rsi"
     145             :   );
     146             : }
     147             : 
     148             : #define HAVE_CPU_DETECTION
     149             : #endif
     150             : #endif
     151             : 
     152             : #ifdef HAVE_CPU_DETECTION
     153             : static inline bool
     154             : HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit)
     155             : {
     156             :   // Check that the level in question is supported.
     157             :   volatile int regs[4];
     158             :   __cpuid((int *)regs, level & 0x80000000u);
     159             :   if (unsigned(regs[0]) < level)
     160             :     return false;
     161             :   __cpuid((int *)regs, level);
     162             :   return !!(unsigned(regs[reg]) & bit);
     163             : }
     164             : #endif
     165             : #endif
     166             : 
     167             : #ifdef MOZ_ENABLE_FREETYPE
     168             : extern "C" {
     169             : 
     170             : FT_Face
     171           6 : mozilla_NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex)
     172             : {
     173           6 :   return mozilla::gfx::Factory::NewFTFace(aFTLibrary, aFileName, aFaceIndex);
     174             : }
     175             : 
     176             : FT_Face
     177           0 : mozilla_NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex)
     178             : {
     179           0 :   return mozilla::gfx::Factory::NewFTFaceFromData(aFTLibrary, aData, aDataSize, aFaceIndex);
     180             : }
     181             : 
     182             : void
     183           0 : mozilla_ReleaseFTFace(FT_Face aFace)
     184             : {
     185           0 :   mozilla::gfx::Factory::ReleaseFTFace(aFace);
     186           0 : }
     187             : 
     188             : }
     189             : #endif
     190             : 
     191             : namespace mozilla {
     192             : namespace gfx {
     193             : 
     194             : // In Gecko, this value is managed by gfx.logging.level in gfxPrefs.
     195             : int32_t LoggingPrefs::sGfxLogLevel = LOG_DEFAULT;
     196             : 
     197             : #ifdef MOZ_ENABLE_FREETYPE
     198             : FT_Library Factory::mFTLibrary = nullptr;
     199             : Mutex* Factory::mFTLock = nullptr;
     200             : #endif
     201             : 
     202             : #ifdef WIN32
     203             : static uint32_t mDeviceSeq = 0;
     204             : ID3D11Device *Factory::mD3D11Device = nullptr;
     205             : ID2D1Device *Factory::mD2D1Device = nullptr;
     206             : IDWriteFactory *Factory::mDWriteFactory = nullptr;
     207             : bool Factory::mDWriteFactoryInitialized = false;
     208             : Mutex* Factory::mDWriteFactoryLock = nullptr;
     209             : #endif
     210             : 
     211             : DrawEventRecorder *Factory::mRecorder;
     212             : 
     213             : mozilla::gfx::Config* Factory::sConfig = nullptr;
     214             : 
     215             : void
     216           3 : Factory::Init(const Config& aConfig)
     217             : {
     218           3 :   MOZ_ASSERT(!sConfig);
     219           3 :   sConfig = new Config(aConfig);
     220             : 
     221             : #ifdef MOZ_ENABLE_FREETYPE
     222           3 :   mFTLock = new Mutex("Factory::mFTLock");
     223             : #endif
     224             : 
     225             : #ifdef WIN32
     226             :   mDWriteFactoryLock = new Mutex("Factory::mDWriteFactoryLock");
     227             : #endif
     228           3 : }
     229             : 
     230             : void
     231           0 : Factory::ShutDown()
     232             : {
     233           0 :   if (sConfig) {
     234           0 :     delete sConfig->mLogForwarder;
     235           0 :     delete sConfig;
     236           0 :     sConfig = nullptr;
     237             :   }
     238             : 
     239             : #ifdef MOZ_ENABLE_FREETYPE
     240           0 :   mFTLibrary = nullptr;
     241           0 :   if (mFTLock) {
     242           0 :     delete mFTLock;
     243           0 :     mFTLock = nullptr;
     244             :   }
     245             : #endif
     246             : 
     247             : #ifdef WIN32
     248             :   if (mDWriteFactoryLock) {
     249             :     delete mDWriteFactoryLock;
     250             :     mDWriteFactoryLock = nullptr;
     251             :   }
     252             : #endif
     253           0 : }
     254             : 
     255             : bool
     256           1 : Factory::HasSSE2()
     257             : {
     258             : #if defined(__SSE2__) || defined(_M_X64) || \
     259             :     (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
     260             :   // gcc with -msse2 (default on OSX and x86-64)
     261             :   // cl.exe with -arch:SSE2 (default on x64 compiler)
     262           1 :   return true;
     263             : #elif defined(HAVE_CPU_DETECTION)
     264             :   static enum {
     265             :     UNINITIALIZED,
     266             :     NO_SSE2,
     267             :     HAS_SSE2
     268             :   } sDetectionState = UNINITIALIZED;
     269             : 
     270             :   if (sDetectionState == UNINITIALIZED) {
     271             :     sDetectionState = HasCPUIDBit(1u, edx, (1u<<26)) ? HAS_SSE2 : NO_SSE2;
     272             :   }
     273             :   return sDetectionState == HAS_SSE2;
     274             : #else
     275             :   return false;
     276             : #endif
     277             : }
     278             : 
     279             : // If the size is "reasonable", we want gfxCriticalError to assert, so
     280             : // this is the option set up for it.
     281           0 : inline int LoggerOptionsBasedOnSize(const IntSize& aSize)
     282             : {
     283           0 :   return CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize));
     284             : }
     285             : 
     286             : bool
     287           0 : Factory::ReasonableSurfaceSize(const IntSize &aSize)
     288             : {
     289           0 :   return Factory::CheckSurfaceSize(aSize, 8192);
     290             : }
     291             : 
     292             : bool
     293          90 : Factory::AllowedSurfaceSize(const IntSize &aSize)
     294             : {
     295          90 :   if (sConfig) {
     296          90 :     return Factory::CheckSurfaceSize(aSize,
     297             :                                      sConfig->mMaxTextureSize,
     298          90 :                                      sConfig->mMaxAllocSize);
     299             :   }
     300             : 
     301           0 :   return CheckSurfaceSize(aSize);
     302             : }
     303             : 
     304             : bool
     305           0 : Factory::CheckBufferSize(int32_t bufSize)
     306             : {
     307           0 :   return !sConfig || bufSize < sConfig->mMaxAllocSize;
     308             : }
     309             : 
     310             : bool
     311          96 : Factory::CheckSurfaceSize(const IntSize &sz,
     312             :                           int32_t extentLimit,
     313             :                           int32_t allocLimit)
     314             : {
     315          96 :   if (sz.width <= 0 || sz.height <= 0) {
     316           0 :     return false;
     317             :   }
     318             : 
     319             :   // reject images with sides bigger than limit
     320          96 :   if (extentLimit && (sz.width > extentLimit || sz.height > extentLimit)) {
     321           0 :     gfxDebug() << "Surface size too large (exceeds extent limit)!";
     322           0 :     return false;
     323             :   }
     324             : 
     325             :   // assuming 4 bytes per pixel, make sure the allocation size
     326             :   // doesn't overflow a int32_t either
     327          96 :   CheckedInt<int32_t> stride = GetAlignedStride<16>(sz.width, 4);
     328          96 :   if (!stride.isValid() || stride.value() == 0) {
     329           0 :     gfxDebug() << "Surface size too large (stride overflows int32_t)!";
     330           0 :     return false;
     331             :   }
     332             : 
     333          96 :   CheckedInt<int32_t> numBytes = stride * sz.height;
     334          96 :   if (!numBytes.isValid()) {
     335           0 :     gfxDebug() << "Surface size too large (allocation size would overflow int32_t)!";
     336           0 :     return false;
     337             :   }
     338             : 
     339          96 :   if (allocLimit && allocLimit < numBytes.value()) {
     340           0 :     gfxDebug() << "Surface size too large (exceeds allocation limit)!";
     341           0 :     return false;
     342             :   }
     343             : 
     344          96 :   return true;
     345             : }
     346             : 
     347             : already_AddRefed<DrawTarget>
     348          23 : Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat)
     349             : {
     350          23 :   if (!AllowedSurfaceSize(aSize)) {
     351           0 :     gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (CDT) " << aSize;
     352           0 :     return nullptr;
     353             :   }
     354             : 
     355          46 :   RefPtr<DrawTarget> retVal;
     356          23 :   switch (aBackend) {
     357             : #ifdef WIN32
     358             :   case BackendType::DIRECT2D1_1:
     359             :     {
     360             :       RefPtr<DrawTargetD2D1> newTarget;
     361             :       newTarget = new DrawTargetD2D1();
     362             :       if (newTarget->Init(aSize, aFormat)) {
     363             :         retVal = newTarget;
     364             :       }
     365             :       break;
     366             :     }
     367             : #endif
     368             : #ifdef USE_SKIA
     369             :   case BackendType::SKIA:
     370             :     {
     371          46 :       RefPtr<DrawTargetSkia> newTarget;
     372          23 :       newTarget = new DrawTargetSkia();
     373          23 :       if (newTarget->Init(aSize, aFormat)) {
     374          23 :         retVal = newTarget;
     375             :       }
     376          23 :       break;
     377             :     }
     378             : #endif
     379             : #ifdef USE_CAIRO
     380             :   case BackendType::CAIRO:
     381             :     {
     382           0 :       RefPtr<DrawTargetCairo> newTarget;
     383           0 :       newTarget = new DrawTargetCairo();
     384           0 :       if (newTarget->Init(aSize, aFormat)) {
     385           0 :         retVal = newTarget;
     386             :       }
     387           0 :       break;
     388             :     }
     389             : #endif
     390             :   default:
     391           0 :     return nullptr;
     392             :   }
     393             : 
     394          23 :   if (mRecorder && retVal) {
     395           0 :     return MakeAndAddRef<DrawTargetWrapAndRecord>(mRecorder, retVal);
     396             :   }
     397             : 
     398          23 :   if (!retVal) {
     399             :     // Failed
     400           0 :     gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize;
     401             :   }
     402             : 
     403          23 :   return retVal.forget();
     404             : }
     405             : 
     406             : already_AddRefed<DrawTarget>
     407           0 : Factory::CreateWrapAndRecordDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT)
     408             : {
     409           0 :   return MakeAndAddRef<DrawTargetWrapAndRecord>(aRecorder, aDT);
     410             : }
     411             : 
     412             : already_AddRefed<DrawTarget>
     413           0 : Factory::CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT, IntSize aSize)
     414             : {
     415           0 :   return MakeAndAddRef<DrawTargetRecording>(aRecorder, aDT, aSize);
     416             : }
     417             : 
     418             : already_AddRefed<DrawTarget>
     419          37 : Factory::CreateDrawTargetForData(BackendType aBackend,
     420             :                                  unsigned char *aData,
     421             :                                  const IntSize &aSize,
     422             :                                  int32_t aStride,
     423             :                                  SurfaceFormat aFormat,
     424             :                                  bool aUninitialized)
     425             : {
     426          37 :   MOZ_ASSERT(aData);
     427          37 :   if (!AllowedSurfaceSize(aSize)) {
     428           0 :     gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (DTD) " << aSize;
     429           0 :     return nullptr;
     430             :   }
     431             : 
     432          74 :   RefPtr<DrawTarget> retVal;
     433             : 
     434          37 :   switch (aBackend) {
     435             : #ifdef USE_SKIA
     436             :   case BackendType::SKIA:
     437             :     {
     438          74 :       RefPtr<DrawTargetSkia> newTarget;
     439          37 :       newTarget = new DrawTargetSkia();
     440          37 :       if (newTarget->Init(aData, aSize, aStride, aFormat, aUninitialized)) {
     441          37 :         retVal = newTarget;
     442             :       }
     443          37 :       break;
     444             :     }
     445             : #endif
     446             : #ifdef USE_CAIRO
     447             :   case BackendType::CAIRO:
     448             :     {
     449           0 :       RefPtr<DrawTargetCairo> newTarget;
     450           0 :       newTarget = new DrawTargetCairo();
     451           0 :       if (newTarget->Init(aData, aSize, aStride, aFormat)) {
     452           0 :         retVal = newTarget.forget();
     453             :       }
     454           0 :       break;
     455             :     }
     456             : #endif
     457             :   default:
     458           0 :     gfxCriticalNote << "Invalid draw target type specified: " << (int)aBackend;
     459           0 :     return nullptr;
     460             :   }
     461             : 
     462          37 :   if (mRecorder && retVal) {
     463           0 :     return MakeAndAddRef<DrawTargetWrapAndRecord>(mRecorder, retVal, true);
     464             :   }
     465             : 
     466          37 :   if (!retVal) {
     467           0 :     gfxCriticalNote << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize << ", Data: " << hexa((void *)aData) << ", Stride: " << aStride;
     468             :   }
     469             : 
     470          37 :   return retVal.forget();
     471             : }
     472             : 
     473             : already_AddRefed<DrawTarget>
     474           0 : Factory::CreateTiledDrawTarget(const TileSet& aTileSet)
     475             : {
     476           0 :   RefPtr<DrawTargetTiled> dt = new DrawTargetTiled();
     477             : 
     478           0 :   if (!dt->Init(aTileSet)) {
     479           0 :     return nullptr;
     480             :   }
     481             : 
     482           0 :   return dt.forget();
     483             : }
     484             : 
     485             : bool
     486          37 : Factory::DoesBackendSupportDataDrawtarget(BackendType aType)
     487             : {
     488          37 :   switch (aType) {
     489             :   case BackendType::DIRECT2D:
     490             :   case BackendType::DIRECT2D1_1:
     491             :   case BackendType::RECORDING:
     492             :   case BackendType::NONE:
     493             :   case BackendType::BACKEND_LAST:
     494           0 :     return false;
     495             :   case BackendType::CAIRO:
     496             :   case BackendType::SKIA:
     497          37 :     return true;
     498             :   }
     499             : 
     500           0 :   return false;
     501             : }
     502             : 
     503             : uint32_t
     504           1 : Factory::GetMaxSurfaceSize(BackendType aType)
     505             : {
     506           1 :   switch (aType) {
     507             :   case BackendType::CAIRO:
     508           0 :     return DrawTargetCairo::GetMaxSurfaceSize();
     509             : #ifdef USE_SKIA
     510             :   case BackendType::SKIA:
     511           1 :     return DrawTargetSkia::GetMaxSurfaceSize();
     512             : #endif
     513             : #ifdef WIN32
     514             :   case BackendType::DIRECT2D1_1:
     515             :     return DrawTargetD2D1::GetMaxSurfaceSize();
     516             : #endif
     517             :   default:
     518           0 :     return 0;
     519             :   }
     520             : }
     521             : 
     522             : already_AddRefed<ScaledFont>
     523           0 : Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont,
     524             :                                        const RefPtr<UnscaledFont>& aUnscaledFont,
     525             :                                        Float aSize)
     526             : {
     527           0 :   switch (aNativeFont.mType) {
     528             : #ifdef WIN32
     529             :   case NativeFontType::DWRITE_FONT_FACE:
     530             :     {
     531             :       return MakeAndAddRef<ScaledFontDWrite>(static_cast<IDWriteFontFace*>(aNativeFont.mFont), aUnscaledFont, aSize);
     532             :     }
     533             : #if defined(USE_CAIRO) || defined(USE_SKIA)
     534             :   case NativeFontType::GDI_FONT_FACE:
     535             :     {
     536             :       return MakeAndAddRef<ScaledFontWin>(static_cast<LOGFONT*>(aNativeFont.mFont), aUnscaledFont, aSize);
     537             :     }
     538             : #endif
     539             : #endif
     540             : #ifdef XP_DARWIN
     541             :   case NativeFontType::MAC_FONT_FACE:
     542             :     {
     543             :       return MakeAndAddRef<ScaledFontMac>(static_cast<CGFontRef>(aNativeFont.mFont), aUnscaledFont, aSize);
     544             :     }
     545             : #endif
     546             : #if defined(USE_CAIRO) || defined(USE_SKIA_FREETYPE)
     547             :   case NativeFontType::CAIRO_FONT_FACE:
     548             :     {
     549           0 :       return MakeAndAddRef<ScaledFontCairo>(static_cast<cairo_scaled_font_t*>(aNativeFont.mFont), aUnscaledFont, aSize);
     550             :     }
     551             : #endif
     552             :   default:
     553           0 :     gfxWarning() << "Invalid native font type specified.";
     554           0 :     return nullptr;
     555             :   }
     556             : }
     557             : 
     558             : already_AddRefed<NativeFontResource>
     559           0 : Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, BackendType aBackendType, FontType aFontType, void* aFontContext)
     560             : {
     561           0 :   switch (aFontType) {
     562             : #ifdef WIN32
     563             :   case FontType::DWRITE:
     564             :     {
     565             :       bool needsCairo = aBackendType == BackendType::CAIRO ||
     566             :                         aBackendType == BackendType::SKIA;
     567             :       return NativeFontResourceDWrite::Create(aData, aSize, needsCairo);
     568             :     }
     569             :   case FontType::GDI:
     570             :     return NativeFontResourceGDI::Create(aData, aSize);
     571             : #elif defined(XP_DARWIN)
     572             :   case FontType::MAC:
     573             :     return NativeFontResourceMac::Create(aData, aSize);
     574             : #elif defined(MOZ_WIDGET_GTK)
     575             :   case FontType::FONTCONFIG:
     576           0 :     return NativeFontResourceFontconfig::Create(aData, aSize,
     577           0 :                                                 static_cast<FT_Library>(aFontContext));
     578             : #endif
     579             :   default:
     580           0 :     gfxWarning() << "Unable to create requested font resource from truetype data";
     581           0 :     return nullptr;
     582             :   }
     583             : }
     584             : 
     585             : already_AddRefed<UnscaledFont>
     586           0 : Factory::CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength)
     587             : {
     588           0 :   switch (aType) {
     589             : #ifdef WIN32
     590             :   case FontType::GDI:
     591             :     return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength);
     592             : #endif
     593             : #ifdef MOZ_WIDGET_GTK
     594             :   case FontType::FONTCONFIG:
     595           0 :     return UnscaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength);
     596             : #endif
     597             :   default:
     598           0 :     gfxWarning() << "Invalid type specified for UnscaledFont font descriptor";
     599           0 :     return nullptr;
     600             :   }
     601             : }
     602             : 
     603             : already_AddRefed<ScaledFont>
     604           0 : Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont,
     605             :                                    const RefPtr<UnscaledFont>& aUnscaledFont,
     606             :                                    Float aSize,
     607             :                                    cairo_scaled_font_t* aScaledFont)
     608             : {
     609             : #ifdef USE_CAIRO
     610             :   // In theory, we could pull the NativeFont out of the cairo_scaled_font_t*,
     611             :   // but that would require a lot of code that would be otherwise repeated in
     612             :   // various backends.
     613             :   // Therefore, we just reuse CreateScaledFontForNativeFont's implementation.
     614           0 :   RefPtr<ScaledFont> font = CreateScaledFontForNativeFont(aNativeFont, aUnscaledFont, aSize);
     615           0 :   static_cast<ScaledFontBase*>(font.get())->SetCairoScaledFont(aScaledFont);
     616           0 :   return font.forget();
     617             : #else
     618             :   return nullptr;
     619             : #endif
     620             : }
     621             : 
     622             : #ifdef MOZ_WIDGET_GTK
     623             : already_AddRefed<ScaledFont>
     624          21 : Factory::CreateScaledFontForFontconfigFont(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern,
     625             :                                            const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize)
     626             : {
     627          21 :   return MakeAndAddRef<ScaledFontFontconfig>(aScaledFont, aPattern, aUnscaledFont, aSize);
     628             : }
     629             : #endif
     630             : 
     631             : already_AddRefed<DrawTarget>
     632           0 : Factory::CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB)
     633             : {
     634           0 :   MOZ_ASSERT(targetA && targetB);
     635             : 
     636             :   RefPtr<DrawTarget> newTarget =
     637           0 :     new DrawTargetDual(targetA, targetB);
     638             : 
     639           0 :   RefPtr<DrawTarget> retVal = newTarget;
     640             : 
     641           0 :   if (mRecorder) {
     642           0 :     retVal = new DrawTargetWrapAndRecord(mRecorder, retVal);
     643             :   }
     644             : 
     645           0 :   return retVal.forget();
     646             : }
     647             : 
     648             : 
     649             : #ifdef MOZ_ENABLE_FREETYPE
     650             : void
     651           3 : Factory::SetFTLibrary(FT_Library aFTLibrary)
     652             : {
     653           3 :   mFTLibrary = aFTLibrary;
     654           3 : }
     655             : 
     656             : FT_Library
     657           0 : Factory::GetFTLibrary()
     658             : {
     659           0 :   MOZ_ASSERT(mFTLibrary);
     660           0 :   return mFTLibrary;
     661             : }
     662             : 
     663             : FT_Library
     664           0 : Factory::NewFTLibrary()
     665             : {
     666             :   FT_Library library;
     667           0 :   if (FT_Init_FreeType(&library) != FT_Err_Ok) {
     668           0 :     return nullptr;
     669             :   }
     670           0 :   return library;
     671             : }
     672             : 
     673             : void
     674           0 : Factory::ReleaseFTLibrary(FT_Library aFTLibrary)
     675             : {
     676           0 :   FT_Done_FreeType(aFTLibrary);
     677           0 : }
     678             : 
     679             : FT_Face
     680          10 : Factory::NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex)
     681             : {
     682          10 :   MOZ_ASSERT(mFTLock);
     683          20 :   MutexAutoLock lock(*mFTLock);
     684          10 :   if (!aFTLibrary) {
     685           4 :     aFTLibrary = mFTLibrary;
     686             :   }
     687             :   FT_Face face;
     688          10 :   if (FT_New_Face(aFTLibrary, aFileName, aFaceIndex, &face) != FT_Err_Ok) {
     689           0 :     return nullptr;
     690             :   }
     691          10 :   return face;
     692             : }
     693             : 
     694             : FT_Face
     695           0 : Factory::NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex)
     696             : {
     697           0 :   MOZ_ASSERT(mFTLock);
     698           0 :   MutexAutoLock lock(*mFTLock);
     699           0 :   if (!aFTLibrary) {
     700           0 :     aFTLibrary = mFTLibrary;
     701             :   }
     702             :   FT_Face face;
     703           0 :   if (FT_New_Memory_Face(aFTLibrary, aData, aDataSize, aFaceIndex, &face) != FT_Err_Ok) {
     704           0 :     return nullptr;
     705             :   }
     706           0 :   return face;
     707             : }
     708             : 
     709             : void
     710           2 : Factory::ReleaseFTFace(FT_Face aFace)
     711             : {
     712             :   // May be called during shutdown when the lock is already destroyed.
     713             :   // However, there are no other threads using the face by this point,
     714             :   // so it is safe to skip locking if the lock is not around.
     715           2 :   if (mFTLock) {
     716           2 :     mFTLock->Lock();
     717             :   }
     718           2 :   FT_Done_Face(aFace);
     719           2 :   if (mFTLock) {
     720           2 :     mFTLock->Unlock();
     721             :   }
     722           2 : }
     723             : #endif
     724             : 
     725             : #ifdef WIN32
     726             : already_AddRefed<DrawTarget>
     727             : Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat)
     728             : {
     729             :   MOZ_ASSERT(aTexture);
     730             : 
     731             :   RefPtr<DrawTargetD2D1> newTarget;
     732             : 
     733             :   newTarget = new DrawTargetD2D1();
     734             :   if (newTarget->Init(aTexture, aFormat)) {
     735             :     RefPtr<DrawTarget> retVal = newTarget;
     736             : 
     737             :     if (mRecorder) {
     738             :       retVal = new DrawTargetWrapAndRecord(mRecorder, retVal, true);
     739             :     }
     740             : 
     741             :     return retVal.forget();
     742             :   }
     743             : 
     744             :   gfxWarning() << "Failed to create draw target for D3D11 texture.";
     745             : 
     746             :   // Failed
     747             :   return nullptr;
     748             : }
     749             : 
     750             : bool
     751             : Factory::SetDirect3D11Device(ID3D11Device *aDevice)
     752             : {
     753             :   mD3D11Device = aDevice;
     754             : 
     755             :   if (mD2D1Device) {
     756             :     mD2D1Device->Release();
     757             :     mD2D1Device = nullptr;
     758             :   }
     759             : 
     760             :   if (!aDevice) {
     761             :     return true;
     762             :   }
     763             : 
     764             :   RefPtr<ID2D1Factory1> factory = D2DFactory1();
     765             : 
     766             :   RefPtr<IDXGIDevice> device;
     767             :   aDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(device));
     768             :   HRESULT hr = factory->CreateDevice(device, &mD2D1Device);
     769             :   if (FAILED(hr)) {
     770             :     gfxCriticalError() << "[D2D1] Failed to create gfx factory's D2D1 device, code: " << hexa(hr);
     771             : 
     772             :     mD3D11Device = nullptr;
     773             :     return false;
     774             :   } else {
     775             :     mDeviceSeq++;
     776             :   }
     777             : 
     778             :   return true;
     779             : }
     780             : 
     781             : ID3D11Device*
     782             : Factory::GetDirect3D11Device()
     783             : {
     784             :   return mD3D11Device;
     785             : }
     786             : 
     787             : ID2D1Device*
     788             : Factory::GetD2D1Device()
     789             : {
     790             :   return mD2D1Device;
     791             : }
     792             : 
     793             : uint32_t
     794             : Factory::GetD2D1DeviceSeq()
     795             : {
     796             :   return mDeviceSeq;
     797             : }
     798             : 
     799             : IDWriteFactory*
     800             : Factory::GetDWriteFactory()
     801             : {
     802             :   return mDWriteFactory;
     803             : }
     804             : 
     805             : IDWriteFactory*
     806             : Factory::EnsureDWriteFactory()
     807             : {
     808             :   MOZ_ASSERT(mDWriteFactoryLock);
     809             :   MutexAutoLock lock(*mDWriteFactoryLock);
     810             : 
     811             :   if (mDWriteFactoryInitialized) {
     812             :     return mDWriteFactory;
     813             :   }
     814             : 
     815             :   mDWriteFactoryInitialized = true;
     816             : 
     817             :   HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll");
     818             :   decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
     819             :     GetProcAddress(dwriteModule, "DWriteCreateFactory");
     820             : 
     821             :   if (!createDWriteFactory) {
     822             :     gfxWarning() << "Failed to locate DWriteCreateFactory function.";
     823             :     return nullptr;
     824             :   }
     825             : 
     826             :   HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
     827             :                                    reinterpret_cast<IUnknown**>(&mDWriteFactory));
     828             : 
     829             :   if (FAILED(hr)) {
     830             :     gfxWarning() << "Failed to create DWrite Factory.";
     831             :   }
     832             : 
     833             :   return mDWriteFactory;
     834             : }
     835             : 
     836             : bool
     837             : Factory::SupportsD2D1()
     838             : {
     839             :   return !!D2DFactory1();
     840             : }
     841             : 
     842             : BYTE sSystemTextQuality = CLEARTYPE_QUALITY;
     843             : void
     844             : Factory::UpdateSystemTextQuality()
     845             : {
     846             : #ifdef WIN32
     847             :   gfx::UpdateSystemTextQuality();
     848             : #endif
     849             : }
     850             : 
     851             : uint64_t
     852             : Factory::GetD2DVRAMUsageDrawTarget()
     853             : {
     854             :   return DrawTargetD2D1::mVRAMUsageDT;
     855             : }
     856             : 
     857             : uint64_t
     858             : Factory::GetD2DVRAMUsageSourceSurface()
     859             : {
     860             :   return DrawTargetD2D1::mVRAMUsageSS;
     861             : }
     862             : 
     863             : void
     864             : Factory::D2DCleanup()
     865             : {
     866             :   if (mD2D1Device) {
     867             :     mD2D1Device->Release();
     868             :     mD2D1Device = nullptr;
     869             :   }
     870             :   DrawTargetD2D1::CleanupD2D();
     871             : }
     872             : 
     873             : already_AddRefed<ScaledFont>
     874             : Factory::CreateScaledFontForDWriteFont(IDWriteFontFace* aFontFace,
     875             :                                        const gfxFontStyle* aStyle,
     876             :                                        const RefPtr<UnscaledFont>& aUnscaledFont,
     877             :                                        float aSize,
     878             :                                        bool aUseEmbeddedBitmap,
     879             :                                        bool aForceGDIMode,
     880             :                                        IDWriteRenderingParams* aParams,
     881             :                                        Float aGamma,
     882             :                                        Float aContrast)
     883             : {
     884             :   return MakeAndAddRef<ScaledFontDWrite>(aFontFace, aUnscaledFont, aSize,
     885             :                                          aUseEmbeddedBitmap, aForceGDIMode,
     886             :                                          aParams, aGamma, aContrast,
     887             :                                          aStyle);
     888             : }
     889             : 
     890             : #endif // XP_WIN
     891             : 
     892             : #ifdef USE_SKIA_GPU
     893             : already_AddRefed<DrawTarget>
     894           0 : Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext,
     895             :                                            const IntSize &aSize,
     896             :                                            SurfaceFormat aFormat)
     897             : {
     898           0 :   RefPtr<DrawTarget> newTarget = new DrawTargetSkia();
     899           0 :   if (!newTarget->InitWithGrContext(aGrContext, aSize, aFormat)) {
     900           0 :     return nullptr;
     901             :   }
     902           0 :   return newTarget.forget();
     903             : }
     904             : 
     905             : #endif // USE_SKIA_GPU
     906             : 
     907             : #ifdef USE_SKIA
     908             : already_AddRefed<DrawTarget>
     909           0 : Factory::CreateDrawTargetWithSkCanvas(SkCanvas* aCanvas)
     910             : {
     911           0 :   RefPtr<DrawTargetSkia> newTarget = new DrawTargetSkia();
     912           0 :   if (!newTarget->Init(aCanvas)) {
     913           0 :     return nullptr;
     914             :   }
     915           0 :   return newTarget.forget();
     916             : }
     917             : #endif
     918             : 
     919             : void
     920           0 : Factory::PurgeAllCaches()
     921             : {
     922           0 : }
     923             : 
     924             : already_AddRefed<DrawTarget>
     925           0 : Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat)
     926             : {
     927           0 :   if (!AllowedSurfaceSize(aSize)) {
     928           0 :     gfxWarning() << "Allowing surface with invalid size (Cairo) " << aSize;
     929             :   }
     930             : 
     931           0 :   RefPtr<DrawTarget> retVal;
     932             : 
     933             : #ifdef USE_CAIRO
     934           0 :   RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo();
     935             : 
     936           0 :   if (newTarget->Init(aSurface, aSize, aFormat)) {
     937           0 :     retVal = newTarget;
     938             :   }
     939             : 
     940           0 :   if (mRecorder && retVal) {
     941           0 :     return MakeAndAddRef<DrawTargetWrapAndRecord>(mRecorder, retVal, true);
     942             :   }
     943             : #endif
     944           0 :   return retVal.forget();
     945             : }
     946             : 
     947             : already_AddRefed<SourceSurface>
     948           0 : Factory::CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat aFormat)
     949             : {
     950           0 :   if (aSize.width <= 0 || aSize.height <= 0) {
     951           0 :     gfxWarning() << "Can't create a SourceSurface without a valid size";
     952           0 :     return nullptr;
     953             :   }
     954             : 
     955             : #ifdef USE_CAIRO
     956           0 :   return MakeAndAddRef<SourceSurfaceCairo>(aSurface, aSize, aFormat);
     957             : #else
     958             :   return nullptr;
     959             : #endif
     960             : }
     961             : 
     962             : already_AddRefed<DataSourceSurface>
     963          83 : Factory::CreateWrappingDataSourceSurface(uint8_t *aData,
     964             :                                          int32_t aStride,
     965             :                                          const IntSize &aSize,
     966             :                                          SurfaceFormat aFormat,
     967             :                                          SourceSurfaceDeallocator aDeallocator /* = nullptr */,
     968             :                                          void* aClosure /* = nullptr */)
     969             : {
     970             :   // Just check for negative/zero size instead of the full AllowedSurfaceSize() - since
     971             :   // the data is already allocated we do not need to check for a possible overflow - it
     972             :   // already worked.
     973          83 :   if (aSize.width <= 0 || aSize.height <= 0) {
     974           0 :     return nullptr;
     975             :   }
     976          83 :   if (!aDeallocator && aClosure) {
     977           0 :     return nullptr;
     978             :   }
     979             : 
     980          83 :   MOZ_ASSERT(aData);
     981             : 
     982         166 :   RefPtr<SourceSurfaceRawData> newSurf = new SourceSurfaceRawData();
     983          83 :   newSurf->InitWrappingData(aData, aSize, aStride, aFormat, aDeallocator, aClosure);
     984             : 
     985          83 :   return newSurf.forget();
     986             : }
     987             : 
     988             : #ifdef XP_DARWIN
     989             : already_AddRefed<GlyphRenderingOptions>
     990             : Factory::CreateCGGlyphRenderingOptions(const Color &aFontSmoothingBackgroundColor)
     991             : {
     992             :   return MakeAndAddRef<GlyphRenderingOptionsCG>(aFontSmoothingBackgroundColor);
     993             : }
     994             : #endif
     995             : 
     996             : already_AddRefed<DataSourceSurface>
     997           0 : Factory::CreateDataSourceSurface(const IntSize &aSize,
     998             :                                  SurfaceFormat aFormat,
     999             :                                  bool aZero)
    1000             : {
    1001           0 :   if (!AllowedSurfaceSize(aSize)) {
    1002           0 :     gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (DSS) " << aSize;
    1003           0 :     return nullptr;
    1004             :   }
    1005             : 
    1006             :   // Skia doesn't support RGBX, so memset RGBX to 0xFF
    1007           0 :   bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8;
    1008           0 :   uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0;
    1009             : 
    1010           0 :   RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
    1011           0 :   if (newSurf->Init(aSize, aFormat, clearSurface, clearValue)) {
    1012           0 :     return newSurf.forget();
    1013             :   }
    1014             : 
    1015           0 :   gfxWarning() << "CreateDataSourceSurface failed in init";
    1016           0 :   return nullptr;
    1017             : }
    1018             : 
    1019             : already_AddRefed<DataSourceSurface>
    1020           0 : Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize,
    1021             :                                            SurfaceFormat aFormat,
    1022             :                                            int32_t aStride,
    1023             :                                            bool aZero)
    1024             : {
    1025           0 :   if (!AllowedSurfaceSize(aSize) ||
    1026           0 :       aStride < aSize.width * BytesPerPixel(aFormat)) {
    1027           0 :     gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "CreateDataSourceSurfaceWithStride failed with bad stride " << aStride << ", " << aSize << ", " << aFormat;
    1028           0 :     return nullptr;
    1029             :   }
    1030             : 
    1031             :   // Skia doesn't support RGBX, so memset RGBX to 0xFF
    1032           0 :   bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8;
    1033           0 :   uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0;
    1034             : 
    1035           0 :   RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
    1036           0 :   if (newSurf->Init(aSize, aFormat, clearSurface, clearValue, aStride)) {
    1037           0 :     return newSurf.forget();
    1038             :   }
    1039             : 
    1040           0 :   gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "CreateDataSourceSurfaceWithStride failed to initialize " << aSize << ", " << aFormat << ", " << aStride << ", " << aZero;
    1041           0 :   return nullptr;
    1042             : }
    1043             : 
    1044             : void
    1045           0 : Factory::CopyDataSourceSurface(DataSourceSurface* aSource,
    1046             :                                DataSourceSurface* aDest)
    1047             : {
    1048             :   // Don't worry too much about speed.
    1049           0 :   MOZ_ASSERT(aSource->GetSize() == aDest->GetSize());
    1050           0 :   MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
    1051             :              aSource->GetFormat() == SurfaceFormat::R8G8B8X8 ||
    1052             :              aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
    1053             :              aSource->GetFormat() == SurfaceFormat::B8G8R8X8);
    1054           0 :   MOZ_ASSERT(aDest->GetFormat() == SurfaceFormat::R8G8B8A8 ||
    1055             :              aDest->GetFormat() == SurfaceFormat::R8G8B8X8 ||
    1056             :              aDest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
    1057             :              aDest->GetFormat() == SurfaceFormat::B8G8R8X8 ||
    1058             :              aDest->GetFormat() == SurfaceFormat::R5G6B5_UINT16);
    1059             : 
    1060             :   DataSourceSurface::MappedSurface srcMap;
    1061             :   DataSourceSurface::MappedSurface destMap;
    1062           0 :   if (!aSource->Map(DataSourceSurface::MapType::READ, &srcMap) ||
    1063           0 :     !aDest->Map(DataSourceSurface::MapType::WRITE, &destMap)) {
    1064           0 :     MOZ_ASSERT(false, "CopyDataSourceSurface: Failed to map surface.");
    1065             :     return;
    1066             :   }
    1067             : 
    1068           0 :   SwizzleData(srcMap.mData, srcMap.mStride, aSource->GetFormat(),
    1069           0 :               destMap.mData, destMap.mStride, aDest->GetFormat(),
    1070           0 :               aSource->GetSize());
    1071             : 
    1072           0 :   aSource->Unmap();
    1073           0 :   aDest->Unmap();
    1074           0 : }
    1075             : 
    1076             : already_AddRefed<DrawEventRecorder>
    1077           0 : Factory::CreateEventRecorderForFile(const char *aFilename)
    1078             : {
    1079           0 :   return MakeAndAddRef<DrawEventRecorderFile>(aFilename);
    1080             : }
    1081             : 
    1082             : void
    1083           3 : Factory::SetGlobalEventRecorder(DrawEventRecorder *aRecorder)
    1084             : {
    1085           3 :   mRecorder = aRecorder;
    1086           3 : }
    1087             : 
    1088             : // static
    1089             : void
    1090           0 : CriticalLogger::OutputMessage(const std::string &aString,
    1091             :                               int aLevel, bool aNoNewline)
    1092             : {
    1093           0 :   if (Factory::GetLogForwarder()) {
    1094           0 :     Factory::GetLogForwarder()->Log(aString);
    1095             :   }
    1096             : 
    1097           0 :   BasicLogger::OutputMessage(aString, aLevel, aNoNewline);
    1098           0 : }
    1099             : 
    1100             : void
    1101           0 : CriticalLogger::CrashAction(LogReason aReason)
    1102             : {
    1103           0 :   if (Factory::GetLogForwarder()) {
    1104           0 :     Factory::GetLogForwarder()->CrashAction(aReason);
    1105             :   }
    1106           0 : }
    1107             : 
    1108             : } // namespace gfx
    1109             : } // namespace mozilla

Generated by: LCOV version 1.13