Factory.cpp (38988B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "2D.h" 8 #include "Swizzle.h" 9 10 #ifdef USE_CAIRO 11 # include "DrawTargetCairo.h" 12 # include "PathCairo.h" 13 # include "SourceSurfaceCairo.h" 14 #endif 15 16 #include "DrawTargetSkia.h" 17 #include "PathSkia.h" 18 #include "ScaledFontBase.h" 19 20 #if defined(WIN32) 21 # include "ScaledFontWin.h" 22 # include "NativeFontResourceGDI.h" 23 # include "UnscaledFontGDI.h" 24 #endif 25 26 #ifdef XP_DARWIN 27 # include "ScaledFontMac.h" 28 # include "NativeFontResourceMac.h" 29 # include "UnscaledFontMac.h" 30 #endif 31 32 #ifdef MOZ_WIDGET_GTK 33 # include "ScaledFontFontconfig.h" 34 # include "NativeFontResourceFreeType.h" 35 # include "UnscaledFontFreeType.h" 36 #endif 37 38 #ifdef MOZ_WIDGET_ANDROID 39 # include "ScaledFontFreeType.h" 40 # include "NativeFontResourceFreeType.h" 41 # include "UnscaledFontFreeType.h" 42 #endif 43 44 #ifdef WIN32 45 # include "ScaledFontDWrite.h" 46 # include "NativeFontResourceDWrite.h" 47 # include "UnscaledFontDWrite.h" 48 # include <d3d10_1.h> 49 # include <stdlib.h> 50 # include "HelpersWin.h" 51 # include "ImageContainer.h" 52 # include "mozilla/layers/LayersSurfaces.h" 53 # include "mozilla/layers/TextureD3D11.h" 54 # include "mozilla/layers/VideoProcessorD3D11.h" 55 # include "nsWindowsHelpers.h" 56 #endif 57 58 #include "DrawTargetOffset.h" 59 #include "DrawTargetRecording.h" 60 #include "PathRecording.h" 61 62 #include "SourceSurfaceRawData.h" 63 64 #include "mozilla/CheckedInt.h" 65 66 #ifdef MOZ_ENABLE_FREETYPE 67 # include "ft2build.h" 68 # include FT_FREETYPE_H 69 #endif 70 #include "mozilla/StaticPrefs_gfx.h" 71 72 #if defined(MOZ_LOGGING) 73 GFX2D_API mozilla::LogModule* GetGFX2DLog() { 74 static mozilla::LazyLogModule sLog("gfx2d"); 75 return sLog; 76 } 77 #endif 78 79 // The following code was largely taken from xpcom/glue/SSE.cpp and 80 // made a little simpler. 81 enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; 82 83 #ifdef HAVE_CPUID_H 84 85 # if !(defined(__SSE2__) || defined(_M_X64) || \ 86 (defined(_M_IX86_FP) && _M_IX86_FP >= 2)) || \ 87 !defined(__SSE4__) 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 HasCPUIDBit(unsigned int level, CPUIDRegister reg, 92 unsigned int bit) { 93 unsigned int regs[4]; 94 return __get_cpuid(level, ®s[0], ®s[1], ®s[2], ®s[3]) && 95 (regs[reg] & bit); 96 } 97 # endif 98 99 # define HAVE_CPU_DETECTION 100 #else 101 102 # if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64)) 103 // MSVC 2005 or later supports __cpuid by intrin.h 104 # include <intrin.h> 105 106 # define HAVE_CPU_DETECTION 107 # elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__)) 108 109 // Define a function identical to MSVC function. 110 # ifdef __i386 111 static void __cpuid(int CPUInfo[4], int InfoType) { 112 asm("xchg %esi, %ebx\n" 113 "cpuid\n" 114 "movl %eax, (%edi)\n" 115 "movl %ebx, 4(%edi)\n" 116 "movl %ecx, 8(%edi)\n" 117 "movl %edx, 12(%edi)\n" 118 "xchg %esi, %ebx\n" 119 : 120 : "a"(InfoType), // %eax 121 "D"(CPUInfo) // %edi 122 : "%ecx", "%edx", "%esi"); 123 } 124 # else 125 static void __cpuid(int CPUInfo[4], int InfoType) { 126 asm("xchg %rsi, %rbx\n" 127 "cpuid\n" 128 "movl %eax, (%rdi)\n" 129 "movl %ebx, 4(%rdi)\n" 130 "movl %ecx, 8(%rdi)\n" 131 "movl %edx, 12(%rdi)\n" 132 "xchg %rsi, %rbx\n" 133 : 134 : "a"(InfoType), // %eax 135 "D"(CPUInfo) // %rdi 136 : "%ecx", "%edx", "%rsi"); 137 } 138 139 # define HAVE_CPU_DETECTION 140 # endif 141 # endif 142 143 # ifdef HAVE_CPU_DETECTION 144 static inline bool HasCPUIDBit(unsigned int level, CPUIDRegister reg, 145 unsigned int bit) { 146 // Check that the level in question is supported. 147 volatile int regs[4]; 148 __cpuid((int*)regs, level & 0x80000000u); 149 if (unsigned(regs[0]) < level) return false; 150 __cpuid((int*)regs, level); 151 return !!(unsigned(regs[reg]) & bit); 152 } 153 # endif 154 #endif 155 156 #ifdef MOZ_ENABLE_FREETYPE 157 extern "C" { 158 159 void mozilla_AddRefSharedFTFace(void* aContext) { 160 if (aContext) { 161 static_cast<mozilla::gfx::SharedFTFace*>(aContext)->AddRef(); 162 } 163 } 164 165 void mozilla_ReleaseSharedFTFace(void* aContext, void* aOwner) { 166 if (aContext) { 167 auto* sharedFace = static_cast<mozilla::gfx::SharedFTFace*>(aContext); 168 sharedFace->ForgetLockOwner(aOwner); 169 sharedFace->Release(); 170 } 171 } 172 173 void mozilla_ForgetSharedFTFaceLockOwner(void* aContext, void* aOwner) { 174 static_cast<mozilla::gfx::SharedFTFace*>(aContext)->ForgetLockOwner(aOwner); 175 } 176 177 int mozilla_LockSharedFTFace(void* aContext, 178 void* aOwner) MOZ_NO_THREAD_SAFETY_ANALYSIS { 179 return int(static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Lock(aOwner)); 180 } 181 182 void mozilla_UnlockSharedFTFace(void* aContext) MOZ_NO_THREAD_SAFETY_ANALYSIS { 183 static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Unlock(); 184 } 185 186 FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, 187 int32_t aFlags) { 188 return mozilla::gfx::Factory::LoadFTGlyph(aFace, aGlyphIndex, aFlags); 189 } 190 191 void mozilla_LockFTLibrary(FT_Library aFTLibrary) { 192 mozilla::gfx::Factory::LockFTLibrary(aFTLibrary); 193 } 194 195 void mozilla_UnlockFTLibrary(FT_Library aFTLibrary) { 196 mozilla::gfx::Factory::UnlockFTLibrary(aFTLibrary); 197 } 198 } 199 #endif 200 201 namespace mozilla::gfx { 202 203 #ifdef MOZ_ENABLE_FREETYPE 204 FT_Library Factory::mFTLibrary = nullptr; 205 StaticMutex Factory::mFTLock; 206 207 already_AddRefed<SharedFTFace> FTUserFontData::CloneFace(int aFaceIndex) { 208 if (mFontData) { 209 RefPtr<SharedFTFace> face = Factory::NewSharedFTFaceFromData( 210 nullptr, mFontData, mLength, aFaceIndex, this); 211 if (!face || 212 (FT_Select_Charmap(face->GetFace(), FT_ENCODING_UNICODE) != FT_Err_Ok && 213 FT_Select_Charmap(face->GetFace(), FT_ENCODING_MS_SYMBOL) != 214 FT_Err_Ok)) { 215 return nullptr; 216 } 217 return face.forget(); 218 } 219 FT_Face face = Factory::NewFTFace(nullptr, mFilename.c_str(), aFaceIndex); 220 if (face) { 221 return MakeAndAddRef<SharedFTFace>(face, this); 222 } 223 return nullptr; 224 } 225 #endif 226 227 #ifdef WIN32 228 // Note: mDeviceLock must be held when mutating these values. 229 StaticRefPtr<ID3D11Device> Factory::mD3D11Device; 230 StaticRefPtr<IDWriteFactory> Factory::mDWriteFactory; 231 StaticRefPtr<IDWriteFontCollection> Factory::mDWriteSystemFonts; 232 StaticMutex Factory::mDeviceLock; 233 #endif 234 235 SubpixelOrder Factory::mSubpixelOrder = SubpixelOrder::UNKNOWN; 236 237 mozilla::gfx::Config* Factory::sConfig = nullptr; 238 239 void Factory::Init(const Config& aConfig) { 240 MOZ_ASSERT(!sConfig); 241 sConfig = new Config(aConfig); 242 243 #ifdef XP_DARWIN 244 NativeFontResourceMac::RegisterMemoryReporter(); 245 #else 246 NativeFontResource::RegisterMemoryReporter(); 247 #endif 248 249 SourceSurfaceAlignedRawData::RegisterMemoryReporter(); 250 } 251 252 void Factory::ShutDown() { 253 if (sConfig) { 254 delete sConfig->mLogForwarder; 255 delete sConfig; 256 sConfig = nullptr; 257 } 258 259 #ifdef MOZ_ENABLE_FREETYPE 260 mFTLibrary = nullptr; 261 #endif 262 } 263 264 bool Factory::HasSSE2() { 265 #if defined(__SSE2__) || defined(_M_X64) || \ 266 (defined(_M_IX86_FP) && _M_IX86_FP >= 2) 267 // gcc with -msse2 (default on OSX and x86-64) 268 // cl.exe with -arch:SSE2 (default on x64 compiler) 269 return true; 270 #elif defined(HAVE_CPU_DETECTION) 271 static enum { 272 UNINITIALIZED, 273 NO_SSE2, 274 HAS_SSE2 275 } sDetectionState = UNINITIALIZED; 276 277 if (sDetectionState == UNINITIALIZED) { 278 sDetectionState = HasCPUIDBit(1u, edx, (1u << 26)) ? HAS_SSE2 : NO_SSE2; 279 } 280 return sDetectionState == HAS_SSE2; 281 #else 282 return false; 283 #endif 284 } 285 286 bool Factory::HasSSE4() { 287 #if defined(__SSE4__) 288 // gcc with -msse2 (default on OSX and x86-64) 289 // cl.exe with -arch:SSE2 (default on x64 compiler) 290 return true; 291 #elif defined(HAVE_CPU_DETECTION) 292 static enum { 293 UNINITIALIZED, 294 NO_SSE4, 295 HAS_SSE4 296 } sDetectionState = UNINITIALIZED; 297 298 if (sDetectionState == UNINITIALIZED) { 299 sDetectionState = HasCPUIDBit(1u, ecx, (1u << 19)) ? HAS_SSE4 : NO_SSE4; 300 } 301 return sDetectionState == HAS_SSE4; 302 #else 303 return false; 304 #endif 305 } 306 307 // If the size is "reasonable", we want gfxCriticalError to assert, so 308 // this is the option set up for it. 309 inline int LoggerOptionsBasedOnSize(const IntSize& aSize) { 310 return CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize)); 311 } 312 313 bool Factory::ReasonableSurfaceSize(const IntSize& aSize) { 314 return Factory::CheckSurfaceSize(aSize, kReasonableSurfaceSize); 315 } 316 317 bool Factory::AllowedSurfaceSize(const IntSize& aSize) { 318 if (sConfig) { 319 return Factory::CheckSurfaceSize(aSize, sConfig->mMaxTextureSize, 320 sConfig->mMaxAllocSize); 321 } 322 323 return CheckSurfaceSize(aSize); 324 } 325 326 bool Factory::CheckSurfaceSize(const IntSize& sz, int32_t extentLimit, 327 int32_t allocLimit) { 328 if (sz.width <= 0 || sz.height <= 0) { 329 return false; 330 } 331 332 // reject images with sides bigger than limit 333 if (extentLimit && (sz.width > extentLimit || sz.height > extentLimit)) { 334 gfxDebug() << "Surface size too large (exceeds extent limit)!"; 335 return false; 336 } 337 338 // assuming 4 bytes per pixel, make sure the allocation size 339 // doesn't overflow a int32_t either 340 CheckedInt<int32_t> stride = GetAlignedStride<16>(sz.width, 4); 341 if (!stride.isValid() || stride.value() == 0) { 342 gfxDebug() << "Surface size too large (stride overflows int32_t)!"; 343 return false; 344 } 345 346 CheckedInt<int32_t> numBytes = stride * sz.height; 347 if (!numBytes.isValid()) { 348 gfxDebug() 349 << "Surface size too large (allocation size would overflow int32_t)!"; 350 return false; 351 } 352 353 if (allocLimit && allocLimit < numBytes.value()) { 354 gfxDebug() << "Surface size too large (exceeds allocation limit)!"; 355 return false; 356 } 357 358 return true; 359 } 360 361 already_AddRefed<DrawTarget> Factory::CreateDrawTarget(BackendType aBackend, 362 const IntSize& aSize, 363 SurfaceFormat aFormat) { 364 if (!AllowedSurfaceSize(aSize)) { 365 gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) 366 << "Failed to allocate a surface due to invalid size (CDT) " << aSize; 367 return nullptr; 368 } 369 370 RefPtr<DrawTarget> retVal; 371 switch (aBackend) { 372 case BackendType::SKIA: { 373 RefPtr<DrawTargetSkia> newTarget; 374 newTarget = new DrawTargetSkia(); 375 if (newTarget->Init(aSize, aFormat)) { 376 retVal = newTarget; 377 } 378 break; 379 } 380 #ifdef USE_CAIRO 381 case BackendType::CAIRO: { 382 RefPtr<DrawTargetCairo> newTarget; 383 newTarget = new DrawTargetCairo(); 384 if (newTarget->Init(aSize, aFormat)) { 385 retVal = newTarget; 386 } 387 break; 388 } 389 #endif 390 default: 391 return nullptr; 392 } 393 394 if (!retVal) { 395 // Failed 396 gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) 397 << "Failed to create DrawTarget, Type: " << int(aBackend) 398 << " Size: " << aSize; 399 } 400 401 return retVal.forget(); 402 } 403 404 already_AddRefed<PathBuilder> Factory::CreatePathBuilder(BackendType aBackend, 405 FillRule aFillRule) { 406 switch (aBackend) { 407 case BackendType::SKIA: 408 case BackendType::WEBGL: 409 return PathBuilderSkia::Create(aFillRule); 410 #ifdef USE_CAIRO 411 case BackendType::CAIRO: 412 return PathBuilderCairo::Create(aFillRule); 413 #endif 414 case BackendType::RECORDING: 415 return do_AddRef(new PathBuilderRecording(BackendType::SKIA, aFillRule)); 416 default: 417 gfxCriticalNote << "Invalid PathBuilder type specified: " 418 << (int)aBackend; 419 return nullptr; 420 } 421 } 422 423 already_AddRefed<PathBuilder> Factory::CreateSimplePathBuilder() { 424 return CreatePathBuilder(BackendType::SKIA); 425 } 426 427 already_AddRefed<DrawTarget> Factory::CreateRecordingDrawTarget( 428 DrawEventRecorder* aRecorder, DrawTarget* aDT, IntRect aRect) { 429 return MakeAndAddRef<DrawTargetRecording>(aRecorder, aDT, aRect); 430 } 431 432 already_AddRefed<DrawTarget> Factory::CreateDrawTargetForData( 433 BackendType aBackend, unsigned char* aData, const IntSize& aSize, 434 int32_t aStride, SurfaceFormat aFormat, bool aUninitialized, 435 bool aIsClear) { 436 MOZ_ASSERT(aData); 437 if (!AllowedSurfaceSize(aSize)) { 438 gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) 439 << "Failed to allocate a surface due to invalid size (DTD) " << aSize; 440 return nullptr; 441 } 442 443 RefPtr<DrawTarget> retVal; 444 445 switch (aBackend) { 446 case BackendType::SKIA: { 447 RefPtr<DrawTargetSkia> newTarget; 448 newTarget = new DrawTargetSkia(); 449 if (newTarget->Init(aData, aSize, aStride, aFormat, aUninitialized, 450 aIsClear)) { 451 retVal = newTarget; 452 } 453 break; 454 } 455 #ifdef USE_CAIRO 456 case BackendType::CAIRO: { 457 RefPtr<DrawTargetCairo> newTarget; 458 newTarget = new DrawTargetCairo(); 459 if (newTarget->Init(aData, aSize, aStride, aFormat)) { 460 retVal = std::move(newTarget); 461 } 462 break; 463 } 464 #endif 465 default: 466 gfxCriticalNote << "Invalid draw target type specified: " 467 << (int)aBackend; 468 return nullptr; 469 } 470 471 if (!retVal) { 472 gfxCriticalNote << "Failed to create DrawTarget, Type: " << int(aBackend) 473 << " Size: " << aSize << ", Data: " << hexa((void*)aData) 474 << ", Stride: " << aStride; 475 } 476 477 return retVal.forget(); 478 } 479 480 already_AddRefed<DrawTarget> Factory::CreateOffsetDrawTarget( 481 DrawTarget* aDrawTarget, IntPoint aTileOrigin) { 482 RefPtr<DrawTargetOffset> dt = new DrawTargetOffset(); 483 484 if (!dt->Init(aDrawTarget, aTileOrigin)) { 485 return nullptr; 486 } 487 488 return dt.forget(); 489 } 490 491 bool Factory::DoesBackendSupportDataDrawtarget(BackendType aType) { 492 switch (aType) { 493 case BackendType::RECORDING: 494 case BackendType::NONE: 495 case BackendType::BACKEND_LAST: 496 case BackendType::WEBRENDER_TEXT: 497 case BackendType::WEBGL: 498 return false; 499 case BackendType::CAIRO: 500 case BackendType::SKIA: 501 return true; 502 } 503 504 return false; 505 } 506 507 uint32_t Factory::GetMaxSurfaceSize(BackendType aType) { 508 switch (aType) { 509 case BackendType::CAIRO: 510 return DrawTargetCairo::GetMaxSurfaceSize(); 511 case BackendType::SKIA: 512 return DrawTargetSkia::GetMaxSurfaceSize(); 513 default: 514 return 0; 515 } 516 } 517 518 already_AddRefed<NativeFontResource> Factory::CreateNativeFontResource( 519 const uint8_t* aData, uint32_t aSize, FontType aFontType, 520 void* aFontContext) { 521 switch (aFontType) { 522 #ifdef WIN32 523 case FontType::DWRITE: 524 return NativeFontResourceDWrite::Create(aData, aSize); 525 case FontType::GDI: 526 return NativeFontResourceGDI::Create(aData, aSize); 527 #elif defined(XP_DARWIN) 528 case FontType::MAC: 529 return NativeFontResourceMac::Create(aData, aSize); 530 #elif defined(MOZ_WIDGET_GTK) 531 case FontType::FONTCONFIG: 532 return NativeFontResourceFontconfig::Create( 533 aData, aSize, static_cast<FT_Library>(aFontContext)); 534 #elif defined(MOZ_WIDGET_ANDROID) 535 case FontType::FREETYPE: 536 return NativeFontResourceFreeType::Create( 537 aData, aSize, static_cast<FT_Library>(aFontContext)); 538 #endif 539 default: 540 gfxWarning() 541 << "Unable to create requested font resource from truetype data"; 542 return nullptr; 543 } 544 } 545 546 already_AddRefed<UnscaledFont> Factory::CreateUnscaledFontFromFontDescriptor( 547 FontType aType, const uint8_t* aData, uint32_t aDataLength, 548 uint32_t aIndex) { 549 switch (aType) { 550 #ifdef WIN32 551 case FontType::DWRITE: 552 return UnscaledFontDWrite::CreateFromFontDescriptor(aData, aDataLength, 553 aIndex); 554 case FontType::GDI: 555 return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength, 556 aIndex); 557 #elif defined(XP_DARWIN) 558 case FontType::MAC: 559 return UnscaledFontMac::CreateFromFontDescriptor(aData, aDataLength, 560 aIndex); 561 #elif defined(MOZ_WIDGET_GTK) 562 case FontType::FONTCONFIG: 563 return UnscaledFontFontconfig::CreateFromFontDescriptor( 564 aData, aDataLength, aIndex); 565 #elif defined(MOZ_WIDGET_ANDROID) 566 case FontType::FREETYPE: 567 return UnscaledFontFreeType::CreateFromFontDescriptor(aData, aDataLength, 568 aIndex); 569 #endif 570 default: 571 gfxWarning() << "Invalid type specified for UnscaledFont font descriptor"; 572 return nullptr; 573 } 574 } 575 576 #ifdef XP_DARWIN 577 already_AddRefed<ScaledFont> Factory::CreateScaledFontForMacFont( 578 CGFontRef aCGFont, const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize, 579 bool aUseFontSmoothing, bool aApplySyntheticBold, bool aHasColorGlyphs) { 580 return MakeAndAddRef<ScaledFontMac>(aCGFont, aUnscaledFont, aSize, false, 581 aUseFontSmoothing, aApplySyntheticBold, 582 aHasColorGlyphs); 583 } 584 #endif 585 586 #ifdef MOZ_WIDGET_GTK 587 already_AddRefed<ScaledFont> Factory::CreateScaledFontForFontconfigFont( 588 const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize, 589 RefPtr<SharedFTFace> aFace, FcPattern* aPattern) { 590 return MakeAndAddRef<ScaledFontFontconfig>(std::move(aFace), aPattern, 591 aUnscaledFont, aSize); 592 } 593 #endif 594 595 #ifdef MOZ_WIDGET_ANDROID 596 already_AddRefed<ScaledFont> Factory::CreateScaledFontForFreeTypeFont( 597 const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize, 598 RefPtr<SharedFTFace> aFace, bool aApplySyntheticBold) { 599 return MakeAndAddRef<ScaledFontFreeType>(std::move(aFace), aUnscaledFont, 600 aSize, aApplySyntheticBold); 601 } 602 #endif 603 604 void Factory::SetSubpixelOrder(SubpixelOrder aOrder) { 605 mSubpixelOrder = aOrder; 606 } 607 608 SubpixelOrder Factory::GetSubpixelOrder() { return mSubpixelOrder; } 609 610 #ifdef MOZ_ENABLE_FREETYPE 611 SharedFTFace::SharedFTFace(FT_Face aFace, SharedFTFaceData* aData) 612 : mFace(aFace), 613 mData(aData), 614 mLock("SharedFTFace::mLock"), 615 mLastLockOwner(nullptr) { 616 if (mData) { 617 mData->BindData(); 618 } 619 } 620 621 SharedFTFace::~SharedFTFace() { 622 Factory::ReleaseFTFace(mFace); 623 if (mData) { 624 mData->ReleaseData(); 625 } 626 } 627 628 void Factory::SetFTLibrary(FT_Library aFTLibrary) { mFTLibrary = aFTLibrary; } 629 630 FT_Library Factory::GetFTLibrary() { 631 MOZ_ASSERT(mFTLibrary); 632 return mFTLibrary; 633 } 634 635 FT_Library Factory::NewFTLibrary() { 636 FT_Library library; 637 if (FT_Init_FreeType(&library) != FT_Err_Ok) { 638 return nullptr; 639 } 640 return library; 641 } 642 643 void Factory::ReleaseFTLibrary(FT_Library aFTLibrary) { 644 FT_Done_FreeType(aFTLibrary); 645 } 646 647 void Factory::LockFTLibrary(FT_Library aFTLibrary) 648 MOZ_CAPABILITY_ACQUIRE(mFTLock) MOZ_NO_THREAD_SAFETY_ANALYSIS { 649 mFTLock.Lock(); 650 } 651 652 void Factory::UnlockFTLibrary(FT_Library aFTLibrary) 653 MOZ_CAPABILITY_RELEASE(mFTLock) MOZ_NO_THREAD_SAFETY_ANALYSIS { 654 mFTLock.Unlock(); 655 } 656 657 FT_Face Factory::NewFTFace(FT_Library aFTLibrary, const char* aFileName, 658 int aFaceIndex) { 659 StaticMutexAutoLock lock(mFTLock); 660 if (!aFTLibrary) { 661 aFTLibrary = mFTLibrary; 662 } 663 FT_Face face; 664 if (FT_New_Face(aFTLibrary, aFileName, aFaceIndex, &face) != FT_Err_Ok) { 665 return nullptr; 666 } 667 return face; 668 } 669 670 already_AddRefed<SharedFTFace> Factory::NewSharedFTFace(FT_Library aFTLibrary, 671 const char* aFilename, 672 int aFaceIndex) { 673 FT_Face face = NewFTFace(aFTLibrary, aFilename, aFaceIndex); 674 if (!face) { 675 return nullptr; 676 } 677 678 RefPtr<FTUserFontData> data; 679 # ifdef ANDROID 680 // If the font has variations, we may later need to "clone" it in 681 // UnscaledFontFreeType::CreateScaledFont. To support this, we attach an 682 // FTUserFontData that records the filename used to instantiate the face. 683 if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { 684 data = new FTUserFontData(aFilename); 685 } 686 # endif 687 return MakeAndAddRef<SharedFTFace>(face, data); 688 } 689 690 FT_Face Factory::NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, 691 size_t aDataSize, int aFaceIndex) { 692 StaticMutexAutoLock lock(mFTLock); 693 if (!aFTLibrary) { 694 aFTLibrary = mFTLibrary; 695 } 696 FT_Face face; 697 if (FT_New_Memory_Face(aFTLibrary, aData, aDataSize, aFaceIndex, &face) != 698 FT_Err_Ok) { 699 return nullptr; 700 } 701 return face; 702 } 703 704 already_AddRefed<SharedFTFace> Factory::NewSharedFTFaceFromData( 705 FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, 706 int aFaceIndex, SharedFTFaceData* aSharedData) { 707 if (FT_Face face = 708 NewFTFaceFromData(aFTLibrary, aData, aDataSize, aFaceIndex)) { 709 return MakeAndAddRef<SharedFTFace>(face, aSharedData); 710 } else { 711 return nullptr; 712 } 713 } 714 715 void Factory::ReleaseFTFace(FT_Face aFace) { 716 StaticMutexAutoLock lock(mFTLock); 717 FT_Done_Face(aFace); 718 } 719 720 FT_Error Factory::LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, 721 int32_t aFlags) { 722 StaticMutexAutoLock lock(mFTLock); 723 return FT_Load_Glyph(aFace, aGlyphIndex, aFlags); 724 } 725 #endif 726 727 #ifdef WIN32 728 bool Factory::SetDirect3D11Device(ID3D11Device* aDevice) { 729 MOZ_RELEASE_ASSERT(NS_IsMainThread()); 730 731 StaticMutexAutoLock lock(mDeviceLock); 732 733 mD3D11Device = aDevice; 734 return true; 735 } 736 737 RefPtr<ID3D11Device> Factory::GetDirect3D11Device() { 738 StaticMutexAutoLock lock(mDeviceLock); 739 return mD3D11Device; 740 } 741 742 RefPtr<IDWriteFactory> Factory::GetDWriteFactory() { 743 StaticMutexAutoLock lock(mDeviceLock); 744 return mDWriteFactory; 745 } 746 747 RefPtr<IDWriteFactory> Factory::EnsureDWriteFactory() { 748 StaticMutexAutoLock lock(mDeviceLock); 749 750 if (mDWriteFactory) { 751 return mDWriteFactory; 752 } 753 754 HMODULE dwriteModule = LoadLibrarySystem32(L"dwrite.dll"); 755 decltype(DWriteCreateFactory)* createDWriteFactory = 756 (decltype(DWriteCreateFactory)*)GetProcAddress(dwriteModule, 757 "DWriteCreateFactory"); 758 759 if (!createDWriteFactory) { 760 gfxWarning() << "Failed to locate DWriteCreateFactory function."; 761 return nullptr; 762 } 763 764 HRESULT hr = 765 createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), 766 reinterpret_cast<IUnknown**>(&mDWriteFactory)); 767 768 if (FAILED(hr)) { 769 gfxWarning() << "Failed to create DWrite Factory."; 770 } 771 772 return mDWriteFactory; 773 } 774 775 RefPtr<IDWriteFontCollection> Factory::GetDWriteSystemFonts(bool aUpdate) { 776 StaticMutexAutoLock lock(mDeviceLock); 777 778 if (mDWriteSystemFonts && !aUpdate) { 779 return mDWriteSystemFonts; 780 } 781 782 if (!mDWriteFactory) { 783 if ((rand() & 0x3f) == 0) { 784 gfxCriticalError(int(gfx::LogOptions::AssertOnCall)) 785 << "Failed to create DWrite factory"; 786 } else { 787 gfxWarning() << "Failed to create DWrite factory"; 788 } 789 790 return nullptr; 791 } 792 793 RefPtr<IDWriteFontCollection> systemFonts; 794 HRESULT hr = 795 mDWriteFactory->GetSystemFontCollection(getter_AddRefs(systemFonts)); 796 if (FAILED(hr) || !systemFonts) { 797 // only crash some of the time so those experiencing this problem 798 // don't stop using Firefox 799 if ((rand() & 0x3f) == 0) { 800 gfxCriticalError(int(gfx::LogOptions::AssertOnCall)) 801 << "Failed to create DWrite system font collection"; 802 } else { 803 gfxWarning() << "Failed to create DWrite system font collection"; 804 } 805 return nullptr; 806 } 807 mDWriteSystemFonts = systemFonts; 808 809 return mDWriteSystemFonts; 810 } 811 812 BYTE sSystemTextQuality = CLEARTYPE_QUALITY; 813 void Factory::SetSystemTextQuality(uint8_t aQuality) { 814 sSystemTextQuality = aQuality; 815 } 816 817 already_AddRefed<ScaledFont> Factory::CreateScaledFontForDWriteFont( 818 IDWriteFontFace* aFontFace, const gfxFontStyle* aStyle, 819 const RefPtr<UnscaledFont>& aUnscaledFont, float aSize, 820 bool aUseEmbeddedBitmap, bool aUseMultistrikeBold, bool aGDIForced) { 821 return MakeAndAddRef<ScaledFontDWrite>( 822 aFontFace, aUnscaledFont, aSize, aUseEmbeddedBitmap, aUseMultistrikeBold, 823 aGDIForced, aStyle); 824 } 825 826 already_AddRefed<ScaledFont> Factory::CreateScaledFontForGDIFont( 827 const void* aLogFont, const RefPtr<UnscaledFont>& aUnscaledFont, 828 Float aSize) { 829 return MakeAndAddRef<ScaledFontWin>(static_cast<const LOGFONT*>(aLogFont), 830 aUnscaledFont, aSize); 831 } 832 #endif // WIN32 833 834 already_AddRefed<DrawTarget> Factory::CreateDrawTargetWithSkCanvas( 835 SkCanvas* aCanvas) { 836 RefPtr<DrawTargetSkia> newTarget = new DrawTargetSkia(); 837 if (!newTarget->Init(aCanvas)) { 838 return nullptr; 839 } 840 return newTarget.forget(); 841 } 842 843 void Factory::PurgeAllCaches() {} 844 845 already_AddRefed<DrawTarget> Factory::CreateDrawTargetForCairoSurface( 846 cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat) { 847 if (!AllowedSurfaceSize(aSize)) { 848 gfxWarning() << "Allowing surface with invalid size (Cairo) " << aSize; 849 } 850 851 RefPtr<DrawTarget> retVal; 852 853 #ifdef USE_CAIRO 854 RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo(); 855 856 if (newTarget->Init(aSurface, aSize, aFormat)) { 857 retVal = newTarget; 858 } 859 #endif 860 return retVal.forget(); 861 } 862 863 already_AddRefed<SourceSurface> Factory::CreateSourceSurfaceForCairoSurface( 864 cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat aFormat) { 865 if (aSize.width <= 0 || aSize.height <= 0) { 866 gfxWarning() << "Can't create a SourceSurface without a valid size"; 867 return nullptr; 868 } 869 870 #ifdef USE_CAIRO 871 return MakeAndAddRef<SourceSurfaceCairo>(aSurface, aSize, aFormat); 872 #else 873 return nullptr; 874 #endif 875 } 876 877 already_AddRefed<DataSourceSurface> Factory::CreateWrappingDataSourceSurface( 878 uint8_t* aData, int32_t aStride, const IntSize& aSize, 879 SurfaceFormat aFormat, 880 SourceSurfaceDeallocator aDeallocator /* = nullptr */, 881 void* aClosure /* = nullptr */) { 882 // Just check for negative/zero size instead of the full AllowedSurfaceSize() 883 // - since the data is already allocated we do not need to check for a 884 // possible overflow - it already worked. 885 if (aSize.width <= 0 || aSize.height <= 0) { 886 return nullptr; 887 } 888 if (!aDeallocator && aClosure) { 889 return nullptr; 890 } 891 892 MOZ_ASSERT(aData); 893 894 RefPtr<SourceSurfaceRawData> newSurf = new SourceSurfaceRawData(); 895 newSurf->InitWrappingData(aData, aSize, aStride, aFormat, aDeallocator, 896 aClosure); 897 898 return newSurf.forget(); 899 } 900 901 already_AddRefed<DataSourceSurface> Factory::CreateDataSourceSurface( 902 const IntSize& aSize, SurfaceFormat aFormat, bool aZero) { 903 if (!AllowedSurfaceSize(aSize)) { 904 gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) 905 << "Failed to allocate a surface due to invalid size (DSS) " << aSize; 906 return nullptr; 907 } 908 909 // Skia doesn't support RGBX, so memset RGBX to 0xFF 910 bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8; 911 uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0; 912 913 RefPtr<SourceSurfaceAlignedRawData> newSurf = 914 new SourceSurfaceAlignedRawData(); 915 if (newSurf->Init(aSize, aFormat, clearSurface, clearValue)) { 916 return newSurf.forget(); 917 } 918 919 gfxWarning() << "CreateDataSourceSurface failed in init"; 920 return nullptr; 921 } 922 923 already_AddRefed<DataSourceSurface> Factory::CreateDataSourceSurfaceWithStride( 924 const IntSize& aSize, SurfaceFormat aFormat, int32_t aStride, bool aZero) { 925 if (!AllowedSurfaceSize(aSize) || 926 aStride < aSize.width * BytesPerPixel(aFormat)) { 927 gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) 928 << "CreateDataSourceSurfaceWithStride failed with bad stride " 929 << aStride << ", " << aSize << ", " << aFormat; 930 return nullptr; 931 } 932 933 // Skia doesn't support RGBX, so memset RGBX to 0xFF 934 bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8; 935 uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0; 936 937 RefPtr<SourceSurfaceAlignedRawData> newSurf = 938 new SourceSurfaceAlignedRawData(); 939 if (newSurf->Init(aSize, aFormat, clearSurface, clearValue, aStride)) { 940 return newSurf.forget(); 941 } 942 943 gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) 944 << "CreateDataSourceSurfaceWithStride failed to initialize " << aSize 945 << ", " << aFormat << ", " << aStride << ", " << aZero; 946 return nullptr; 947 } 948 949 already_AddRefed<DataSourceSurface> Factory::CopyDataSourceSurface( 950 DataSourceSurface* aSource) { 951 // Don't worry too much about speed. 952 MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 || 953 aSource->GetFormat() == SurfaceFormat::R8G8B8X8 || 954 aSource->GetFormat() == SurfaceFormat::B8G8R8A8 || 955 aSource->GetFormat() == SurfaceFormat::B8G8R8X8 || 956 aSource->GetFormat() == SurfaceFormat::A8); 957 958 DataSourceSurface::ScopedMap srcMap(aSource, DataSourceSurface::READ); 959 if (NS_WARN_IF(!srcMap.IsMapped())) { 960 MOZ_ASSERT_UNREACHABLE("CopyDataSourceSurface: Failed to map surface."); 961 return nullptr; 962 } 963 964 IntSize size = aSource->GetSize(); 965 SurfaceFormat format = aSource->GetFormat(); 966 967 RefPtr<DataSourceSurface> dst = CreateDataSourceSurfaceWithStride( 968 size, format, srcMap.GetStride(), /* aZero */ false); 969 if (NS_WARN_IF(!dst)) { 970 return nullptr; 971 } 972 973 DataSourceSurface::ScopedMap dstMap(dst, DataSourceSurface::WRITE); 974 if (NS_WARN_IF(!dstMap.IsMapped())) { 975 MOZ_ASSERT_UNREACHABLE("CopyDataSourceSurface: Failed to map surface."); 976 return nullptr; 977 } 978 979 SwizzleData(srcMap.GetData(), srcMap.GetStride(), format, dstMap.GetData(), 980 dstMap.GetStride(), format, size); 981 return dst.forget(); 982 } 983 984 void Factory::CopyDataSourceSurface(DataSourceSurface* aSource, 985 DataSourceSurface* aDest) { 986 // Don't worry too much about speed. 987 MOZ_ASSERT(aSource->GetSize() == aDest->GetSize()); 988 MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 || 989 aSource->GetFormat() == SurfaceFormat::R8G8B8X8 || 990 aSource->GetFormat() == SurfaceFormat::B8G8R8A8 || 991 aSource->GetFormat() == SurfaceFormat::B8G8R8X8 || 992 aSource->GetFormat() == SurfaceFormat::A8); 993 MOZ_ASSERT(aDest->GetFormat() == SurfaceFormat::R8G8B8A8 || 994 aDest->GetFormat() == SurfaceFormat::R8G8B8X8 || 995 aDest->GetFormat() == SurfaceFormat::B8G8R8A8 || 996 aDest->GetFormat() == SurfaceFormat::B8G8R8X8 || 997 aDest->GetFormat() == SurfaceFormat::R5G6B5_UINT16 || 998 aDest->GetFormat() == SurfaceFormat::A8); 999 1000 DataSourceSurface::MappedSurface srcMap; 1001 DataSourceSurface::MappedSurface destMap; 1002 if (!aSource->Map(DataSourceSurface::MapType::READ, &srcMap) || 1003 !aDest->Map(DataSourceSurface::MapType::WRITE, &destMap)) { 1004 MOZ_ASSERT(false, "CopyDataSourceSurface: Failed to map surface."); 1005 return; 1006 } 1007 1008 SwizzleData(srcMap.mData, srcMap.mStride, aSource->GetFormat(), destMap.mData, 1009 destMap.mStride, aDest->GetFormat(), aSource->GetSize()); 1010 1011 aSource->Unmap(); 1012 aDest->Unmap(); 1013 } 1014 1015 #ifdef WIN32 1016 1017 /* static */ 1018 already_AddRefed<DataSourceSurface> 1019 Factory::CreateBGRA8DataSourceSurfaceForD3D11Texture( 1020 ID3D11Texture2D* aSrcTexture, uint32_t aArrayIndex, 1021 gfx::ColorSpace2 aColorSpace, gfx::ColorRange aColorRange) { 1022 D3D11_TEXTURE2D_DESC srcDesc = {0}; 1023 aSrcTexture->GetDesc(&srcDesc); 1024 1025 RefPtr<gfx::DataSourceSurface> destTexture = 1026 gfx::Factory::CreateDataSourceSurface( 1027 IntSize(srcDesc.Width, srcDesc.Height), gfx::SurfaceFormat::B8G8R8A8); 1028 if (NS_WARN_IF(!destTexture)) { 1029 return nullptr; 1030 } 1031 if (!ReadbackTexture(destTexture, aSrcTexture, aArrayIndex, aColorSpace, 1032 aColorRange)) { 1033 return nullptr; 1034 } 1035 return destTexture.forget(); 1036 } 1037 1038 /* static */ nsresult Factory::CreateSdbForD3D11Texture( 1039 ID3D11Texture2D* aSrcTexture, const IntSize& aSrcSize, 1040 layers::SurfaceDescriptorBuffer& aSdBuffer, 1041 const std::function<layers::MemoryOrShmem(uint32_t)>& aAllocate) { 1042 D3D11_TEXTURE2D_DESC srcDesc = {0}; 1043 aSrcTexture->GetDesc(&srcDesc); 1044 if (srcDesc.Width != uint32_t(aSrcSize.width) || 1045 srcDesc.Height != uint32_t(aSrcSize.height) || 1046 srcDesc.Format != DXGI_FORMAT_B8G8R8A8_UNORM) { 1047 return NS_ERROR_NOT_IMPLEMENTED; 1048 } 1049 1050 const auto format = gfx::SurfaceFormat::B8G8R8A8; 1051 uint8_t* buffer = nullptr; 1052 int32_t stride = 0; 1053 nsresult rv = layers::Image::AllocateSurfaceDescriptorBufferRgb( 1054 aSrcSize, format, buffer, aSdBuffer, stride, aAllocate); 1055 if (NS_WARN_IF(NS_FAILED(rv))) { 1056 return rv; 1057 } 1058 1059 if (!ReadbackTexture(buffer, stride, aSrcTexture)) { 1060 return NS_ERROR_FAILURE; 1061 } 1062 1063 return NS_OK; 1064 } 1065 1066 /* static */ 1067 bool Factory::ConvertSourceAndRetryReadback(DataSourceSurface* aDestCpuTexture, 1068 ID3D11Texture2D* aSrcTexture, 1069 uint32_t aArrayIndex, 1070 gfx::ColorSpace2 aColorSpace, 1071 gfx::ColorRange aColorRange) { 1072 MOZ_ASSERT(aDestCpuTexture); 1073 MOZ_ASSERT(aSrcTexture); 1074 1075 RefPtr<ID3D11Device> device; 1076 aSrcTexture->GetDevice(getter_AddRefs(device)); 1077 if (!device) { 1078 gfxWarning() << "Failed to get D3D11 device from source texture"; 1079 return false; 1080 } 1081 1082 CD3D11_TEXTURE2D_DESC desc; 1083 aSrcTexture->GetDesc(&desc); 1084 1085 if (desc.Format != DXGI_FORMAT_NV12 && desc.Format != DXGI_FORMAT_P010 && 1086 desc.Format != DXGI_FORMAT_P016) { 1087 gfxWarning() << "Unexpected DXGI format"; 1088 return false; 1089 } 1090 1091 desc = CD3D11_TEXTURE2D_DESC( 1092 DXGI_FORMAT_B8G8R8A8_UNORM, desc.Width, desc.Height, 1, 1, 1093 D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); 1094 1095 RefPtr<ID3D11Texture2D> newSrcTexture; 1096 HRESULT hr = 1097 device->CreateTexture2D(&desc, nullptr, getter_AddRefs(newSrcTexture)); 1098 if (FAILED(hr)) { 1099 gfxWarning() << "Failed to create newSrcTexture: " << gfx::hexa(hr); 1100 return false; 1101 } 1102 1103 RefPtr<layers::VideoProcessorD3D11> videoProcessor = 1104 layers::VideoProcessorD3D11::Create(device); 1105 if (!videoProcessor) { 1106 gfxWarning() << "Failed to create VideoProcessorD3D11"; 1107 return false; 1108 } 1109 1110 hr = videoProcessor->Init(aDestCpuTexture->GetSize()); 1111 if (FAILED(hr)) { 1112 gfxWarning() << "Failed to init VideoProcessorD3D11" << gfx::hexa(hr); 1113 return false; 1114 } 1115 1116 layers::VideoProcessorD3D11::InputTextureInfo info(aColorSpace, aColorRange, 1117 aArrayIndex, aSrcTexture); 1118 if (!videoProcessor->CallVideoProcessorBlt(info, newSrcTexture)) { 1119 gfxWarning() << "CallVideoProcessorBlt failed"; 1120 return false; 1121 } 1122 1123 return ReadbackTexture(aDestCpuTexture, newSrcTexture, 0, aColorSpace, 1124 aColorRange); 1125 } 1126 1127 /* static */ 1128 bool Factory::ReadbackTexture(DataSourceSurface* aDestCpuTexture, 1129 ID3D11Texture2D* aSrcTexture, 1130 uint32_t aArrayIndex, 1131 gfx::ColorSpace2 aColorSpace, 1132 gfx::ColorRange aColorRange) { 1133 D3D11_TEXTURE2D_DESC srcDesc = {0}; 1134 aSrcTexture->GetDesc(&srcDesc); 1135 1136 // Special case: If the source and destination have different formats and the 1137 // destination is B8G8R8A8 then convert the source to B8G8R8A8 and readback. 1138 if ((srcDesc.Format != DXGIFormat(aDestCpuTexture->GetFormat())) && 1139 (aDestCpuTexture->GetFormat() == SurfaceFormat::B8G8R8A8)) { 1140 return ConvertSourceAndRetryReadback(aDestCpuTexture, aSrcTexture, 1141 aArrayIndex, aColorSpace, aColorRange); 1142 } 1143 1144 if ((IntSize(srcDesc.Width, srcDesc.Height) != aDestCpuTexture->GetSize()) || 1145 (srcDesc.Format != DXGIFormat(aDestCpuTexture->GetFormat()))) { 1146 gfxWarning() << "Attempted readback between incompatible textures"; 1147 return false; 1148 } 1149 1150 gfx::DataSourceSurface::MappedSurface mappedSurface; 1151 if (!aDestCpuTexture->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) { 1152 return false; 1153 } 1154 1155 MOZ_ASSERT(aArrayIndex == 0); 1156 1157 bool ret = 1158 ReadbackTexture(mappedSurface.mData, mappedSurface.mStride, aSrcTexture); 1159 aDestCpuTexture->Unmap(); 1160 return ret; 1161 } 1162 1163 /* static */ 1164 bool Factory::ReadbackTexture(uint8_t* aDestData, int32_t aDestStride, 1165 ID3D11Texture2D* aSrcTexture) { 1166 MOZ_ASSERT(aDestData && aDestStride && aSrcTexture); 1167 1168 RefPtr<ID3D11Device> device; 1169 aSrcTexture->GetDevice(getter_AddRefs(device)); 1170 if (!device) { 1171 gfxWarning() << "Failed to get D3D11 device from source texture"; 1172 return false; 1173 } 1174 1175 RefPtr<ID3D11DeviceContext> context; 1176 device->GetImmediateContext(getter_AddRefs(context)); 1177 if (!context) { 1178 gfxWarning() << "Could not get an immediate D3D11 context"; 1179 return false; 1180 } 1181 1182 RefPtr<IDXGIKeyedMutex> mutex; 1183 HRESULT hr = aSrcTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), 1184 (void**)getter_AddRefs(mutex)); 1185 if (SUCCEEDED(hr) && mutex) { 1186 hr = mutex->AcquireSync(0, 2000); 1187 if (hr != S_OK) { 1188 gfxWarning() << "Could not acquire DXGI surface lock in 2 seconds"; 1189 return false; 1190 } 1191 } 1192 1193 D3D11_TEXTURE2D_DESC srcDesc = {0}; 1194 aSrcTexture->GetDesc(&srcDesc); 1195 srcDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 1196 srcDesc.Usage = D3D11_USAGE_STAGING; 1197 srcDesc.BindFlags = 0; 1198 srcDesc.MiscFlags = 0; 1199 srcDesc.MipLevels = 1; 1200 RefPtr<ID3D11Texture2D> srcCpuTexture; 1201 hr = 1202 device->CreateTexture2D(&srcDesc, nullptr, getter_AddRefs(srcCpuTexture)); 1203 if (FAILED(hr)) { 1204 gfxWarning() << "Could not create source texture for mapping"; 1205 if (mutex) { 1206 mutex->ReleaseSync(0); 1207 } 1208 return false; 1209 } 1210 1211 context->CopyResource(srcCpuTexture, aSrcTexture); 1212 1213 if (mutex) { 1214 mutex->ReleaseSync(0); 1215 mutex = nullptr; 1216 } 1217 1218 D3D11_MAPPED_SUBRESOURCE srcMap; 1219 hr = context->Map(srcCpuTexture, 0, D3D11_MAP_READ, 0, &srcMap); 1220 if (FAILED(hr)) { 1221 gfxWarning() << "Could not map source texture"; 1222 return false; 1223 } 1224 1225 uint32_t width = srcDesc.Width; 1226 uint32_t height = srcDesc.Height; 1227 int bpp = BytesPerPixel(gfx::ToPixelFormat(srcDesc.Format)); 1228 for (uint32_t y = 0; y < height; y++) { 1229 memcpy(aDestData + aDestStride * y, 1230 (unsigned char*)(srcMap.pData) + srcMap.RowPitch * y, width * bpp); 1231 } 1232 1233 context->Unmap(srcCpuTexture, 0); 1234 return true; 1235 } 1236 1237 #endif // WIN32 1238 1239 // static 1240 void CriticalLogger::OutputMessage(const std::string& aString, int aLevel, 1241 bool aNoNewline) { 1242 if (Factory::GetLogForwarder()) { 1243 Factory::GetLogForwarder()->Log(aString); 1244 } 1245 1246 BasicLogger::OutputMessage(aString, aLevel, aNoNewline); 1247 } 1248 1249 void CriticalLogger::CrashAction(LogReason aReason) { 1250 if (Factory::GetLogForwarder()) { 1251 Factory::GetLogForwarder()->CrashAction(aReason); 1252 } 1253 } 1254 1255 #ifdef WIN32 1256 void LogWStr(const wchar_t* aWStr, std::stringstream& aOut) { 1257 int n = 1258 WideCharToMultiByte(CP_ACP, 0, aWStr, -1, nullptr, 0, nullptr, nullptr); 1259 if (n > 1) { 1260 std::vector<char> str(n); 1261 WideCharToMultiByte(CP_ACP, 0, aWStr, -1, str.data(), n, nullptr, nullptr); 1262 aOut << str.data(); 1263 } 1264 } 1265 #endif 1266 1267 } // namespace mozilla::gfx