michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "2D.h" michael@0: michael@0: #ifdef USE_CAIRO michael@0: #include "DrawTargetCairo.h" michael@0: #include "ScaledFontCairo.h" michael@0: #endif michael@0: michael@0: #ifdef USE_SKIA michael@0: #include "DrawTargetSkia.h" michael@0: #include "ScaledFontBase.h" michael@0: #ifdef MOZ_ENABLE_FREETYPE michael@0: #define USE_SKIA_FREETYPE michael@0: #include "ScaledFontCairo.h" michael@0: #endif michael@0: #endif michael@0: michael@0: #if defined(WIN32) && defined(USE_SKIA) michael@0: #include "ScaledFontWin.h" michael@0: #endif michael@0: michael@0: #ifdef XP_MACOSX michael@0: #include "ScaledFontMac.h" michael@0: #endif michael@0: michael@0: michael@0: #ifdef XP_MACOSX michael@0: #include "DrawTargetCG.h" michael@0: #endif michael@0: michael@0: #ifdef WIN32 michael@0: #include "DrawTargetD2D.h" michael@0: #ifdef USE_D2D1_1 michael@0: #include "DrawTargetD2D1.h" michael@0: #endif michael@0: #include "ScaledFontDWrite.h" michael@0: #include michael@0: #include "HelpersD2D.h" michael@0: #endif michael@0: michael@0: #include "DrawTargetDual.h" michael@0: #include "DrawTargetRecording.h" michael@0: michael@0: #include "SourceSurfaceRawData.h" michael@0: michael@0: #include "DrawEventRecorder.h" michael@0: michael@0: #include "Logging.h" michael@0: michael@0: #include "mozilla/CheckedInt.h" michael@0: michael@0: #if defined(DEBUG) || defined(PR_LOGGING) michael@0: GFX2D_API PRLogModuleInfo * michael@0: GetGFX2DLog() michael@0: { michael@0: static PRLogModuleInfo *sLog; michael@0: if (!sLog) michael@0: sLog = PR_NewLogModule("gfx2d"); michael@0: return sLog; michael@0: } michael@0: #endif michael@0: michael@0: // The following code was largely taken from xpcom/glue/SSE.cpp and michael@0: // made a little simpler. michael@0: enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; michael@0: michael@0: #ifdef HAVE_CPUID_H michael@0: michael@0: #if !(defined(__SSE2__) || defined(_M_X64) || \ michael@0: (defined(_M_IX86_FP) && _M_IX86_FP >= 2)) michael@0: // cpuid.h is available on gcc 4.3 and higher on i386 and x86_64 michael@0: #include michael@0: michael@0: static inline bool michael@0: HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit) michael@0: { michael@0: unsigned int regs[4]; michael@0: return __get_cpuid(level, ®s[0], ®s[1], ®s[2], ®s[3]) && michael@0: (regs[reg] & bit); michael@0: } michael@0: #endif michael@0: michael@0: #define HAVE_CPU_DETECTION michael@0: #else michael@0: michael@0: #if defined(_MSC_VER) && _MSC_VER >= 1600 && (defined(_M_IX86) || defined(_M_AMD64)) michael@0: // MSVC 2005 or later supports __cpuid by intrin.h michael@0: // But it does't work on MSVC 2005 with SDK 7.1 (Bug 753772) michael@0: #include michael@0: michael@0: #define HAVE_CPU_DETECTION michael@0: #elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__)) michael@0: michael@0: // Define a function identical to MSVC function. michael@0: #ifdef __i386 michael@0: static void michael@0: __cpuid(int CPUInfo[4], int InfoType) michael@0: { michael@0: asm ( michael@0: "xchg %esi, %ebx\n" michael@0: "cpuid\n" michael@0: "movl %eax, (%edi)\n" michael@0: "movl %ebx, 4(%edi)\n" michael@0: "movl %ecx, 8(%edi)\n" michael@0: "movl %edx, 12(%edi)\n" michael@0: "xchg %esi, %ebx\n" michael@0: : michael@0: : "a"(InfoType), // %eax michael@0: "D"(CPUInfo) // %edi michael@0: : "%ecx", "%edx", "%esi" michael@0: ); michael@0: } michael@0: #else michael@0: static void michael@0: __cpuid(int CPUInfo[4], int InfoType) michael@0: { michael@0: asm ( michael@0: "xchg %rsi, %rbx\n" michael@0: "cpuid\n" michael@0: "movl %eax, (%rdi)\n" michael@0: "movl %ebx, 4(%rdi)\n" michael@0: "movl %ecx, 8(%rdi)\n" michael@0: "movl %edx, 12(%rdi)\n" michael@0: "xchg %rsi, %rbx\n" michael@0: : michael@0: : "a"(InfoType), // %eax michael@0: "D"(CPUInfo) // %rdi michael@0: : "%ecx", "%edx", "%rsi" michael@0: ); michael@0: } michael@0: michael@0: #define HAVE_CPU_DETECTION michael@0: #endif michael@0: #endif michael@0: michael@0: #ifdef HAVE_CPU_DETECTION michael@0: static inline bool michael@0: HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit) michael@0: { michael@0: // Check that the level in question is supported. michael@0: volatile int regs[4]; michael@0: __cpuid((int *)regs, level & 0x80000000u); michael@0: if (unsigned(regs[0]) < level) michael@0: return false; michael@0: __cpuid((int *)regs, level); michael@0: return !!(unsigned(regs[reg]) & bit); michael@0: } michael@0: #endif michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: // XXX - Need to define an API to set this. michael@0: GFX2D_API int sGfxLogLevel = LOG_DEBUG; michael@0: michael@0: #ifdef WIN32 michael@0: ID3D10Device1 *Factory::mD3D10Device; michael@0: #ifdef USE_D2D1_1 michael@0: ID3D11Device *Factory::mD3D11Device; michael@0: ID2D1Device *Factory::mD2D1Device; michael@0: #endif michael@0: #endif michael@0: michael@0: DrawEventRecorder *Factory::mRecorder; michael@0: michael@0: bool michael@0: Factory::HasSSE2() michael@0: { michael@0: #if defined(__SSE2__) || defined(_M_X64) || \ michael@0: (defined(_M_IX86_FP) && _M_IX86_FP >= 2) michael@0: // gcc with -msse2 (default on OSX and x86-64) michael@0: // cl.exe with -arch:SSE2 (default on x64 compiler) michael@0: return true; michael@0: #elif defined(HAVE_CPU_DETECTION) michael@0: return HasCPUIDBit(1u, edx, (1u<<26)); michael@0: #else michael@0: return false; michael@0: #endif michael@0: } michael@0: michael@0: bool michael@0: Factory::CheckSurfaceSize(const IntSize &sz, int32_t limit) michael@0: { michael@0: if (sz.width < 0 || sz.height < 0) { michael@0: gfxDebug() << "Surface width or height < 0!"; michael@0: return false; michael@0: } michael@0: michael@0: // reject images with sides bigger than limit michael@0: if (limit && (sz.width > limit || sz.height > limit)) { michael@0: gfxDebug() << "Surface size too large (exceeds caller's limit)!"; michael@0: return false; michael@0: } michael@0: michael@0: // make sure the surface area doesn't overflow a int32_t michael@0: CheckedInt tmp = sz.width; michael@0: tmp *= sz.height; michael@0: if (!tmp.isValid()) { michael@0: gfxDebug() << "Surface size too large (would overflow)!"; michael@0: return false; michael@0: } michael@0: michael@0: // assuming 4 bytes per pixel, make sure the allocation size michael@0: // doesn't overflow a int32_t either michael@0: CheckedInt stride = sz.width; michael@0: stride *= 4; michael@0: michael@0: // When aligning the stride to 16 bytes, it can grow by up to 15 bytes. michael@0: stride += 16 - 1; michael@0: michael@0: if (!stride.isValid()) { michael@0: gfxDebug() << "Surface size too large (stride overflows int32_t)!"; michael@0: return false; michael@0: } michael@0: michael@0: CheckedInt numBytes = GetAlignedStride<16>(sz.width * 4); michael@0: numBytes *= sz.height; michael@0: if (!numBytes.isValid()) { michael@0: gfxDebug() << "Surface size too large (allocation size would overflow int32_t)!"; michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat) michael@0: { michael@0: if (!CheckSurfaceSize(aSize)) { michael@0: return nullptr; michael@0: } michael@0: michael@0: RefPtr retVal; michael@0: switch (aBackend) { michael@0: #ifdef WIN32 michael@0: case BackendType::DIRECT2D: michael@0: { michael@0: RefPtr newTarget; michael@0: newTarget = new DrawTargetD2D(); michael@0: if (newTarget->Init(aSize, aFormat)) { michael@0: retVal = newTarget; michael@0: } michael@0: break; michael@0: } michael@0: #ifdef USE_D2D1_1 michael@0: case BackendType::DIRECT2D1_1: michael@0: { michael@0: RefPtr newTarget; michael@0: newTarget = new DrawTargetD2D1(); michael@0: if (newTarget->Init(aSize, aFormat)) { michael@0: retVal = newTarget; michael@0: } michael@0: break; michael@0: } michael@0: #endif michael@0: #elif defined XP_MACOSX michael@0: case BackendType::COREGRAPHICS: michael@0: case BackendType::COREGRAPHICS_ACCELERATED: michael@0: { michael@0: RefPtr newTarget; michael@0: newTarget = new DrawTargetCG(); michael@0: if (newTarget->Init(aBackend, aSize, aFormat)) { michael@0: retVal = newTarget; michael@0: } michael@0: break; michael@0: } michael@0: #endif michael@0: #ifdef USE_SKIA michael@0: case BackendType::SKIA: michael@0: { michael@0: RefPtr newTarget; michael@0: newTarget = new DrawTargetSkia(); michael@0: if (newTarget->Init(aSize, aFormat)) { michael@0: retVal = newTarget; michael@0: } michael@0: break; michael@0: } michael@0: #endif michael@0: #ifdef USE_CAIRO michael@0: case BackendType::CAIRO: michael@0: { michael@0: RefPtr newTarget; michael@0: newTarget = new DrawTargetCairo(); michael@0: if (newTarget->Init(aSize, aFormat)) { michael@0: retVal = newTarget; michael@0: } michael@0: break; michael@0: } michael@0: #endif michael@0: default: michael@0: gfxDebug() << "Invalid draw target type specified."; michael@0: return nullptr; michael@0: } michael@0: michael@0: if (mRecorder && retVal) { michael@0: RefPtr recordDT; michael@0: recordDT = new DrawTargetRecording(mRecorder, retVal); michael@0: return recordDT; michael@0: } michael@0: michael@0: if (!retVal) { michael@0: // Failed michael@0: gfxDebug() << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize; michael@0: } michael@0: michael@0: return retVal; michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT) michael@0: { michael@0: return new DrawTargetRecording(aRecorder, aDT); michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateDrawTargetForData(BackendType aBackend, michael@0: unsigned char *aData, michael@0: const IntSize &aSize, michael@0: int32_t aStride, michael@0: SurfaceFormat aFormat) michael@0: { michael@0: if (!CheckSurfaceSize(aSize)) { michael@0: return nullptr; michael@0: } michael@0: michael@0: RefPtr retVal; michael@0: michael@0: switch (aBackend) { michael@0: #ifdef USE_SKIA michael@0: case BackendType::SKIA: michael@0: { michael@0: RefPtr newTarget; michael@0: newTarget = new DrawTargetSkia(); michael@0: newTarget->Init(aData, aSize, aStride, aFormat); michael@0: retVal = newTarget; michael@0: break; michael@0: } michael@0: #endif michael@0: #ifdef XP_MACOSX michael@0: case BackendType::COREGRAPHICS: michael@0: { michael@0: RefPtr newTarget = new DrawTargetCG(); michael@0: if (newTarget->Init(aBackend, aData, aSize, aStride, aFormat)) michael@0: return newTarget; michael@0: break; michael@0: } michael@0: #endif michael@0: #ifdef USE_CAIRO michael@0: case BackendType::CAIRO: michael@0: { michael@0: RefPtr newTarget; michael@0: newTarget = new DrawTargetCairo(); michael@0: if (newTarget->Init(aData, aSize, aStride, aFormat)) { michael@0: retVal = newTarget; michael@0: } michael@0: break; michael@0: } michael@0: #endif michael@0: default: michael@0: gfxDebug() << "Invalid draw target type specified."; michael@0: return nullptr; michael@0: } michael@0: michael@0: if (mRecorder && retVal) { michael@0: RefPtr recordDT = new DrawTargetRecording(mRecorder, retVal, true); michael@0: return recordDT; michael@0: } michael@0: michael@0: if (!retVal) { michael@0: gfxDebug() << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize; michael@0: } michael@0: michael@0: return retVal; michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize) michael@0: { michael@0: switch (aNativeFont.mType) { michael@0: #ifdef WIN32 michael@0: case NativeFontType::DWRITE_FONT_FACE: michael@0: { michael@0: return new ScaledFontDWrite(static_cast(aNativeFont.mFont), aSize); michael@0: } michael@0: #if defined(USE_CAIRO) || defined(USE_SKIA) michael@0: case NativeFontType::GDI_FONT_FACE: michael@0: { michael@0: return new ScaledFontWin(static_cast(aNativeFont.mFont), aSize); michael@0: } michael@0: #endif michael@0: #endif michael@0: #ifdef XP_MACOSX michael@0: case NativeFontType::MAC_FONT_FACE: michael@0: { michael@0: return new ScaledFontMac(static_cast(aNativeFont.mFont), aSize); michael@0: } michael@0: #endif michael@0: #if defined(USE_CAIRO) || defined(USE_SKIA_FREETYPE) michael@0: case NativeFontType::CAIRO_FONT_FACE: michael@0: { michael@0: return new ScaledFontCairo(static_cast(aNativeFont.mFont), aSize); michael@0: } michael@0: #endif michael@0: default: michael@0: gfxWarning() << "Invalid native font type specified."; michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, michael@0: uint32_t aFaceIndex, Float aGlyphSize, michael@0: FontType aType) michael@0: { michael@0: switch (aType) { michael@0: #ifdef WIN32 michael@0: case FontType::DWRITE: michael@0: { michael@0: return new ScaledFontDWrite(aData, aSize, aFaceIndex, aGlyphSize); michael@0: } michael@0: #endif michael@0: default: michael@0: gfxWarning() << "Unable to create requested font type from truetype data"; michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont) michael@0: { michael@0: #ifdef USE_CAIRO michael@0: // In theory, we could pull the NativeFont out of the cairo_scaled_font_t*, michael@0: // but that would require a lot of code that would be otherwise repeated in michael@0: // various backends. michael@0: // Therefore, we just reuse CreateScaledFontForNativeFont's implementation. michael@0: RefPtr font = CreateScaledFontForNativeFont(aNativeFont, aSize); michael@0: static_cast(font.get())->SetCairoScaledFont(aScaledFont); michael@0: return font; michael@0: #else michael@0: return nullptr; michael@0: #endif michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB) michael@0: { michael@0: RefPtr newTarget = michael@0: new DrawTargetDual(targetA, targetB); michael@0: michael@0: RefPtr retVal = newTarget; michael@0: michael@0: if (mRecorder) { michael@0: retVal = new DrawTargetRecording(mRecorder, retVal); michael@0: } michael@0: michael@0: return retVal; michael@0: } michael@0: michael@0: michael@0: #ifdef WIN32 michael@0: TemporaryRef michael@0: Factory::CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat) michael@0: { michael@0: RefPtr newTarget; michael@0: michael@0: newTarget = new DrawTargetD2D(); michael@0: if (newTarget->Init(aTexture, aFormat)) { michael@0: RefPtr retVal = newTarget; michael@0: michael@0: if (mRecorder) { michael@0: retVal = new DrawTargetRecording(mRecorder, retVal, true); michael@0: } michael@0: michael@0: return retVal; michael@0: } michael@0: michael@0: gfxWarning() << "Failed to create draw target for D3D10 texture."; michael@0: michael@0: // Failed michael@0: return nullptr; michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA, michael@0: ID3D10Texture2D *aTextureB, michael@0: SurfaceFormat aFormat) michael@0: { michael@0: RefPtr newTargetA; michael@0: RefPtr newTargetB; michael@0: michael@0: newTargetA = new DrawTargetD2D(); michael@0: if (!newTargetA->Init(aTextureA, aFormat)) { michael@0: gfxWarning() << "Failed to create draw target for D3D10 texture."; michael@0: return nullptr; michael@0: } michael@0: michael@0: newTargetB = new DrawTargetD2D(); michael@0: if (!newTargetB->Init(aTextureB, aFormat)) { michael@0: gfxWarning() << "Failed to create draw target for D3D10 texture."; michael@0: return nullptr; michael@0: } michael@0: michael@0: RefPtr newTarget = michael@0: new DrawTargetDual(newTargetA, newTargetB); michael@0: michael@0: RefPtr retVal = newTarget; michael@0: michael@0: if (mRecorder) { michael@0: retVal = new DrawTargetRecording(mRecorder, retVal); michael@0: } michael@0: michael@0: return retVal; michael@0: } michael@0: michael@0: void michael@0: Factory::SetDirect3D10Device(ID3D10Device1 *aDevice) michael@0: { michael@0: // do not throw on failure; return error codes and disconnect the device michael@0: // On Windows 8 error codes are the default, but on Windows 7 the michael@0: // default is to throw (or perhaps only with some drivers?) michael@0: aDevice->SetExceptionMode(0); michael@0: mD3D10Device = aDevice; michael@0: } michael@0: michael@0: ID3D10Device1* michael@0: Factory::GetDirect3D10Device() michael@0: { michael@0: #ifdef DEBUG michael@0: UINT mode = mD3D10Device->GetExceptionMode(); michael@0: MOZ_ASSERT(0 == mode); michael@0: #endif michael@0: return mD3D10Device; michael@0: } michael@0: michael@0: #ifdef USE_D2D1_1 michael@0: void michael@0: Factory::SetDirect3D11Device(ID3D11Device *aDevice) michael@0: { michael@0: mD3D11Device = aDevice; michael@0: michael@0: RefPtr factory = D2DFactory1(); michael@0: michael@0: RefPtr device; michael@0: aDevice->QueryInterface((IDXGIDevice**)byRef(device)); michael@0: factory->CreateDevice(device, &mD2D1Device); michael@0: } michael@0: michael@0: ID3D11Device* michael@0: Factory::GetDirect3D11Device() michael@0: { michael@0: return mD3D11Device; michael@0: } michael@0: michael@0: ID2D1Device* michael@0: Factory::GetD2D1Device() michael@0: { michael@0: return mD2D1Device; michael@0: } michael@0: #endif michael@0: michael@0: TemporaryRef michael@0: Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams) michael@0: { michael@0: RefPtr options = michael@0: new GlyphRenderingOptionsDWrite(aParams); michael@0: michael@0: return options; michael@0: } michael@0: michael@0: uint64_t michael@0: Factory::GetD2DVRAMUsageDrawTarget() michael@0: { michael@0: return DrawTargetD2D::mVRAMUsageDT; michael@0: } michael@0: michael@0: uint64_t michael@0: Factory::GetD2DVRAMUsageSourceSurface() michael@0: { michael@0: return DrawTargetD2D::mVRAMUsageSS; michael@0: } michael@0: michael@0: void michael@0: Factory::D2DCleanup() michael@0: { michael@0: DrawTargetD2D::CleanupD2D(); michael@0: } michael@0: michael@0: #endif // XP_WIN michael@0: michael@0: #ifdef USE_SKIA_GPU michael@0: TemporaryRef michael@0: Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext, michael@0: const IntSize &aSize, michael@0: SurfaceFormat aFormat) michael@0: { michael@0: RefPtr newTarget = new DrawTargetSkia(); michael@0: if (!newTarget->InitWithGrContext(aGrContext, aSize, aFormat)) { michael@0: return nullptr; michael@0: } michael@0: return newTarget; michael@0: } michael@0: michael@0: #endif // USE_SKIA_GPU michael@0: michael@0: void michael@0: Factory::PurgeAllCaches() michael@0: { michael@0: } michael@0: michael@0: #ifdef USE_SKIA_FREETYPE michael@0: TemporaryRef michael@0: Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting) michael@0: { michael@0: RefPtr options = michael@0: new GlyphRenderingOptionsCairo(); michael@0: michael@0: options->SetHinting(aHinting); michael@0: options->SetAutoHinting(aAutoHinting); michael@0: return options; michael@0: } michael@0: #endif michael@0: michael@0: TemporaryRef michael@0: Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat) michael@0: { michael@0: RefPtr retVal; michael@0: michael@0: #ifdef USE_CAIRO michael@0: RefPtr newTarget = new DrawTargetCairo(); michael@0: michael@0: if (newTarget->Init(aSurface, aSize, aFormat)) { michael@0: retVal = newTarget; michael@0: } michael@0: michael@0: if (mRecorder && retVal) { michael@0: RefPtr recordDT = new DrawTargetRecording(mRecorder, retVal, true); michael@0: return recordDT; michael@0: } michael@0: #endif michael@0: return retVal; michael@0: } michael@0: michael@0: #ifdef XP_MACOSX michael@0: TemporaryRef michael@0: Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize) michael@0: { michael@0: RefPtr retVal; michael@0: michael@0: RefPtr newTarget = new DrawTargetCG(); michael@0: michael@0: if (newTarget->Init(cg, aSize)) { michael@0: retVal = newTarget; michael@0: } michael@0: michael@0: if (mRecorder && retVal) { michael@0: RefPtr recordDT = new DrawTargetRecording(mRecorder, retVal); michael@0: return recordDT; michael@0: } michael@0: return retVal; michael@0: } michael@0: #endif michael@0: michael@0: TemporaryRef michael@0: Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride, michael@0: const IntSize &aSize, michael@0: SurfaceFormat aFormat) michael@0: { michael@0: if (aSize.width <= 0 || aSize.height <= 0) { michael@0: return nullptr; michael@0: } michael@0: michael@0: RefPtr newSurf = new SourceSurfaceRawData(); michael@0: michael@0: if (newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false)) { michael@0: return newSurf; michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateDataSourceSurface(const IntSize &aSize, michael@0: SurfaceFormat aFormat) michael@0: { michael@0: if (!CheckSurfaceSize(aSize)) { michael@0: return nullptr; michael@0: } michael@0: michael@0: RefPtr newSurf = new SourceSurfaceAlignedRawData(); michael@0: if (newSurf->Init(aSize, aFormat)) { michael@0: return newSurf; michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize, michael@0: SurfaceFormat aFormat, michael@0: int32_t aStride) michael@0: { michael@0: if (aStride < aSize.width * BytesPerPixel(aFormat)) { michael@0: return nullptr; michael@0: } michael@0: michael@0: RefPtr newSurf = new SourceSurfaceAlignedRawData(); michael@0: if (newSurf->InitWithStride(aSize, aFormat, aStride)) { michael@0: return newSurf; michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: TemporaryRef michael@0: Factory::CreateEventRecorderForFile(const char *aFilename) michael@0: { michael@0: return new DrawEventRecorderFile(aFilename); michael@0: } michael@0: michael@0: void michael@0: Factory::SetGlobalEventRecorder(DrawEventRecorder *aRecorder) michael@0: { michael@0: mRecorder = aRecorder; michael@0: } michael@0: michael@0: } michael@0: }