/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdefined(XP_WIN) # include "gfxWindowsPlatform.h" # include "mozilla/widget/WinWindowOcclusionTracker.h" #elifdefined(XP_DARWIN) # include "gfxPlatformMac.h" # include "gfxQuartzSurface.h" #elifdefined(MOZ_WIDGET_GTK) # include "gfxPlatformGtk.h" #elifdefined(ANDROID) # include "gfxAndroidPlatform.h" #endif #ifdefined(MOZ_WIDGET_ANDROID) # include "mozilla/jni/Utils.h"// for IsFennec #endif
#ifdef XP_WIN # include "mozilla/WindowsVersion.h" # include "WinUtils.h" #endif
/// This override of the LogForwarder, initially used for the critical graphics /// errors, is sending the log to the crash annotations as well, but only /// if the capacity set with the method below is >= 2. We always retain the /// very first critical message, and the latest capacity-1 messages are /// rotated through. Note that we don't expect the total number of times /// this gets called to be large - it is meant for critical errors only.
bool CrashStatsLogForwarder::UpdateStringsVector(const std::string& aString) { // We want at least the first one and the last one. Otherwise, no point. if (mMaxCapacity < 2) { returnfalse;
}
mIndex += 1;
MOZ_ASSERT(mIndex >= 0);
// index will count 0, 1, 2, ..., max-1, 1, 2, ..., max-1, 1, 2, ...
int32_t index = mIndex ? (mIndex - 1) % (mMaxCapacity - 1) + 1 : 0;
MOZ_ASSERT(index >= 0 && index < (int32_t)mMaxCapacity);
MOZ_ASSERT(index <= mIndex && index <= (int32_t)mBuffer.size());
// Checking for index >= mBuffer.size(), rather than index == mBuffer.size() // just out of paranoia, but we know index <= mBuffer.size().
LoggingRecordEntry newEntry(mIndex, aString, tStamp); if (index >= static_cast<int32_t>(mBuffer.size())) {
mBuffer.push_back(newEntry);
} else {
mBuffer[index] = newEntry;
} returntrue;
}
void CrashStatsLogForwarder::CrashAction(LogReason aReason) { #ifndef RELEASE_OR_BETA // Non-release builds crash by default, but will use telemetry // if this environment variable is present. staticbool useTelemetry = gfxEnv::MOZ_GFX_CRASH_TELEMETRY(); #else // Release builds use telemetry by default, but will crash instead // if this environment variable is present. staticbool useTelemetry = !gfxEnv::MOZ_GFX_CRASH_MOZ_CRASH(); #endif
if (useTelemetry) { // The callers need to assure that aReason is in the range // that the telemetry call below supports. if (NS_IsMainThread()) {
Telemetry::Accumulate(Telemetry::GFX_CRASH, (uint32_t)aReason);
} else {
nsCOMPtr<nsIRunnable> r1 = new CrashTelemetryEvent((uint32_t)aReason);
NS_DispatchToMainThread(r1);
}
} else { // ignoring aReason, we can get the information we need from the stack
MOZ_CRASH("GFX_CRASH");
}
}
/* static */ void gfxPlatform::InitChild(const ContentDeviceData& aData) {
MOZ_ASSERT(XRE_IsContentProcess());
MOZ_ASSERT(!gPlatform, "InitChild() should be called before first GetPlatform()"); // Make the provided initial ContentDeviceData available to the init // routines.
gContentDeviceInitData = &aData;
Init();
gContentDeviceInitData = nullptr;
}
// List of boolean dynamic parameter for WebRender. // // The parameters in this list are: // - The pref name. // - The BoolParameter enum variant (see webrender_api/src/lib.rs) // - A default value. #define WR_BOOL_PARAMETER_LIST(_) \
_("gfx.webrender.batched-texture-uploads", \
wr::BoolParameter::BatchedUploads, true) \
_("gfx.webrender.draw-calls-for-texture-copy", \
wr::BoolParameter::DrawCallsForTextureCopy, true) \
_("gfx.webrender.pbo-uploads", wr::BoolParameter::PboUploads, true) \
_("gfx.webrender.multithreading", wr::BoolParameter::Multithreading, true)
static uint32_t GetSkiaGlyphCacheSize() { // Only increase font cache size on non-android to save memory. #if !defined(MOZ_WIDGET_ANDROID) // 10mb as the default pref cache size on desktop due to talos perf tweaking. // Chromium uses 20mb and skia default uses 2mb. // We don't need to change the font cache count since we usually // cache thrash due to asian character sets in talos. // Only increase memory on the content process
uint32_t cacheSize =
StaticPrefs::gfx_content_skia_font_cache_size_AtStartup() * 1024 * 1024; if (mozilla::BrowserTabsRemoteAutostart()) { return XRE_IsContentProcess() ? cacheSize : kDefaultGlyphCacheSize;
}
class WebRenderMemoryReporter final : public nsIMemoryReporter { public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMEMORYREPORTER
private:
~WebRenderMemoryReporter() = default;
};
// Memory reporter for WebRender. // // The reporting within WebRender is manual and incomplete. We could do a much // more thorough job by depending on the malloc_size_of crate, but integrating // that into WebRender is tricky [1]. // // So the idea is to start with manual reporting for the large allocations // detected by DMD, and see how much that can cover in practice (which may // require a few rounds of iteration). If that approach turns out to be // fundamentally insufficient, we can either duplicate more of the // malloc_size_of functionality in WebRender, or deal with the complexity of a // gecko-only crate dependency. // // [1] See https://bugzilla.mozilla.org/show_bug.cgi?id=1480293#c1 struct WebRenderMemoryReporterHelper {
WebRenderMemoryReporterHelper(nsIHandleReportCallback* aCallback,
nsISupports* aData)
: mCallback(aCallback), mData(aData) {}
nsCOMPtr<nsIHandleReportCallback> mCallback;
nsCOMPtr<nsISupports> mData;
void ReportTotalGPUBytes(size_t aBytes) const {
nsCString path("gfx/webrender/total-gpu-bytes"_ns);
nsCString desc(nsLiteralCString( "Total GPU bytes used by WebRender (should match textures/ sum)"));
ReportInternal(aBytes, path, desc, nsIMemoryReporter::KIND_OTHER);
}
void ReportInternal(size_t aBytes, nsACString& aPath, nsACString& aDesc,
int32_t aKind) const { // Generally, memory reporters pass the empty string as the process name to // indicate "current process". However, if we're using a GPU process, the // measurements will actually take place in that process, and it's easier to // just note that here rather than trying to invoke the memory reporter in // the GPU process.
nsAutoCString processName; if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
GPUParent::GetGPUProcessName(processName);
}
// clang-format off // (For some reason, clang-format gets the second macro right, but totally mangles the first). #define REPORT_INTERNER(id) \
helper.Report(aReport.interning.interners.id, \ "interning/"#id"/interners"); // clang-format on
bool gfxPlatform::HasVariationFontSupport() { // We record the status here: 0 for not supported, 1 for supported. if (sHasVariationFontSupport < 0) { // It doesn't actually matter if we race with another thread setting this, // as any thread will set it to the same value. #ifdefined(XP_WIN)
sHasVariationFontSupport = gfxWindowsPlatform::CheckVariationFontSupport(); #elifdefined(XP_DARWIN)
sHasVariationFontSupport = gfxPlatformMac::CheckVariationFontSupport(); #elifdefined(MOZ_WIDGET_GTK)
sHasVariationFontSupport = gfxPlatformGtk::CheckVariationFontSupport(); #elifdefined(ANDROID)
sHasVariationFontSupport = gfxAndroidPlatform::CheckVariationFontSupport(); #else # error "No gfxPlatform implementation available" #endif
} return sHasVariationFontSupport > 0;
}
void gfxPlatform::Init() {
AUTO_PROFILER_MARKER_TEXT("gfxPlatform", GRAPHICS, {}, "gfxPlatform::Init"_ns);
MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
MOZ_RELEASE_ASSERT(!XRE_IsRDDProcess(), "GFX: Not allowed in RDD process.");
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread.");
MOZ_RELEASE_ASSERT(!gEverInitialized); if (XRE_IsContentProcess()) {
MOZ_RELEASE_ASSERT(gContentDeviceInitData, "Content Process should cal InitChild() before " "first GetPlatform()");
}
gEverInitialized = true;
gfxVars::Initialize();
gfxConfig::Init();
if (XRE_IsParentProcess()) {
GPUProcessManager::Initialize();
RDDProcessManager::Initialize();
if (gFxREmbedded) {
gfxVars::SetFxREmbedded(true);
}
}
// Drop a note in the crash report if we end up forcing an option that could // destabilize things. New items should be appended at the end (of an // existing or in a new section), so that we don't have to know the version to // interpret these cryptic strings.
{
nsAutoCString forcedPrefs; // D2D prefs
forcedPrefs.AppendPrintf( "FP(D%d%d", StaticPrefs::gfx_direct2d_disabled_AtStartup(),
StaticPrefs::gfx_direct2d_force_enabled_AtStartup()); // Layers prefs
forcedPrefs.AppendPrintf( "-L%d%d%d%d",
StaticPrefs::layers_amd_switchable_gfx_enabled_AtStartup(),
StaticPrefs::layers_acceleration_disabled_AtStartup_DoNotUseDirectly(),
StaticPrefs::
layers_acceleration_force_enabled_AtStartup_DoNotUseDirectly(),
StaticPrefs::layers_d3d11_force_warp_AtStartup()); // WebGL prefs
forcedPrefs.AppendPrintf( "-W%d%d%d%d%d%d%d", StaticPrefs::webgl_angle_force_d3d11(),
StaticPrefs::webgl_angle_force_warp(), StaticPrefs::webgl_disabled(),
StaticPrefs::webgl_disable_angle(), StaticPrefs::webgl_dxgl_enabled(),
StaticPrefs::webgl_force_enabled(), StaticPrefs::webgl_msaa_force()); // Prefs that don't fit into any of the other sections
forcedPrefs.AppendPrintf("-T%d%d) ",
StaticPrefs::gfx_android_rgb16_force_AtStartup(),
StaticPrefs::gfx_canvas_accelerated());
ScopedGfxFeatureReporter::AppNote(forcedPrefs);
}
InitMoz2DLogging();
/* Initialize the GfxInfo service. * Note: we can't call functions on GfxInfo that depend * on gPlatform until after it has been initialized * below. GfxInfo initialization annotates our * crash reports so we want to do it before * we try to load any drivers and do device detection
* incase that code crashes. See bug #591561. */
nsCOMPtr<nsIGfxInfo> gfxInfo; /* this currently will only succeed on Windows */
gfxInfo = components::GfxInfo::Service();
if (XRE_IsParentProcess()) { // Some gfxVars must be initialized prior gPlatform for coherent results.
gfxVars::SetDXInterop2Blocked(IsDXInterop2Blocked());
gfxVars::SetDXNV12Blocked(IsDXNV12Blocked());
gfxVars::SetDXP010Blocked(IsDXP010Blocked());
gfxVars::SetDXP016Blocked(IsDXP016Blocked());
}
#ifdefined(XP_WIN)
gPlatform = new gfxWindowsPlatform; #elifdefined(XP_DARWIN)
gPlatform = new gfxPlatformMac; #elifdefined(MOZ_WIDGET_GTK)
gPlatform = new gfxPlatformGtk; #elifdefined(ANDROID)
gPlatform = new gfxAndroidPlatform; #else # error "No gfxPlatform implementation available" #endif
gPlatform->PopulateScreenInfo();
gPlatform->InitAcceleration();
gPlatform->InitWebRenderConfig();
#ifdefined(XP_WIN) // When using WebRender, we defer initialization of the D3D11 devices until // the (rare) cases where they're used. Note that the GPU process where // WebRender runs doesn't initialize gfxPlatform and performs explicit // initialization of the bits it needs. if (XRE_IsParentProcess() && !gfxConfig::IsEnabled(Feature::GPU_PROCESS) &&
StaticPrefs::
gfx_webrender_enabled_no_gpu_process_with_angle_win_AtStartup()) {
gPlatform->EnsureDevicesInitialized();
} #endif
if (XRE_IsParentProcess()) {
mozilla::glean::gpu_process::feature_status.Set(
gfxConfig::GetFeature(Feature::GPU_PROCESS)
.GetStatusAndFailureIdString());
}
if (XRE_IsParentProcess()) { // Create the global vsync source and dispatcher.
RefPtr<VsyncSource> vsyncSource =
gfxPlatform::ForceSoftwareVsync()
? gPlatform->GetSoftwareVsyncSource()
: gPlatform->GetGlobalHardwareVsyncSource();
gPlatform->mVsyncDispatcher = new VsyncDispatcher(vsyncSource);
// Create the sRGB to output display profile transforms. They can be accessed // off the main thread so we want to avoid a race condition.
gPlatform->InitializeCMS();
// This *create* the platform font list instance, but may not *initialize* it // yet if the gfx.font-list.lazy-init.enabled pref is set. The first *use* // of the list will ensure it is initialized. if (!gPlatform->CreatePlatformFontList()) {
MOZ_CRASH("Could not initialize gfxPlatformFontList");
}
gPlatform->mScreenReferenceDrawTarget =
gPlatform->CreateOffscreenContentDrawTarget(IntSize(1, 1),
SurfaceFormat::B8G8R8A8); if (!gPlatform->mScreenReferenceDrawTarget ||
!gPlatform->mScreenReferenceDrawTarget->IsValid()) { // If TDR is detected, create a draw target with software backend // and it should be replaced later when the process gets the device // reset notification. if (!gPlatform->DidRenderingDeviceReset()) {
gfxCriticalError() << "Could not initialize mScreenReferenceDrawTarget";
}
}
if (NS_FAILED(gfxFontCache::Init())) {
MOZ_CRASH("Could not initialize gfxFontCache");
}
// Listen to memory pressure event so we can purge DrawTarget caches
gPlatform->mMemoryPressureObserver =
layers::MemoryPressureObserver::Create(gPlatform);
// Request the imgITools service, implicitly initializing ImageLib.
nsCOMPtr<imgITools> imgTools = do_GetService("@mozilla.org/image/tools;1"); if (!imgTools) {
MOZ_CRASH("Could not initialize ImageLib");
}
RegisterStrongMemoryReporter(new GfxMemoryImageReporter()); if (XRE_IsParentProcess()) {
RegisterStrongAsyncMemoryReporter(new WebRenderMemoryReporter());
}
if (XRE_IsParentProcess()) {
Preferences::Unlock(FONT_VARIATIONS_PREF); if (!gfxPlatform::HasVariationFontSupport()) { // Ensure variation fonts are disabled and the pref is locked.
Preferences::SetBool(FONT_VARIATIONS_PREF, false, PrefValueKind::Default);
Preferences::SetBool(FONT_VARIATIONS_PREF, false);
Preferences::Lock(FONT_VARIATIONS_PREF);
}
}
// Android description is constructed in a way that makes it possible to exceed // the metric's length limit. #ifdefined(ANDROID) if (!adapterDesc.IsEmpty()) {
adapterDesc.Truncate(99);
} #endif
/* static */
int32_t gfxPlatform::MaxTextureSize() { // Make sure we don't completely break rendering because of a typo in the // pref or whatnot. const int32_t kMinSizePref = 2048; return std::max(
kMinSizePref,
StaticPrefs::gfx_max_texture_size_AtStartup_DoNotUseDirectly());
}
/* static */
int32_t gfxPlatform::MaxAllocSize() { // Make sure we don't completely break rendering because of a typo in the // pref or whatnot. const int32_t kMinAllocPref = 10000000; return std::max(kMinAllocPref,
StaticPrefs::gfx_max_alloc_size_AtStartup_DoNotUseDirectly());
}
void gfxPlatform::MaybeInitializeCMS() { if (XRE_IsGPUProcess()) { // Colors in the GPU process should already be managed, so we don't need to // perform color management there.
gCMSInitialized = true; return;
}
Unused << GetPlatform();
}
/* static */ void gfxPlatform::InitMoz2DLogging() { auto fwd = new CrashStatsLogForwarder(
CrashReporter::Annotation::GraphicsCriticalError);
fwd->SetCircularBufferSize(StaticPrefs::gfx_logging_crash_length_AtStartup());
void gfxPlatform::Shutdown() { // In some cases, gPlatform may not be created but Shutdown() called, // e.g., during xpcshell tests. if (!gPlatform) { return;
}
MOZ_ASSERT(!sLayersIPCIsUp);
// These may be called before the corresponding subsystems have actually // started up. That's OK, they can handle it.
gfxFontCache::Shutdown();
gfxGradientCache::Shutdown();
gfxAlphaBoxBlur::ShutdownBlurCache();
gfxGraphiteShaper::Shutdown();
gfxPlatformFontList::Shutdown();
gfxFontMissingGlyphs::Shutdown();
// Free the various non-null transforms and loaded profiles
gPlatform->ShutdownCMS();
// Shut down the default GL context provider.
GLContextProvider::Shutdown();
#ifdefined(XP_WIN) // The above shutdown calls operate on the available context providers on // most platforms. Windows is a "special snowflake", though, and has three // context providers available, so we have to shut all of them down. // We should only support the default GL provider on Windows; then, this // could go away. Unfortunately, we currently support WGL (the default) for // WebGL on Optimus.
GLContextProviderEGL::Shutdown(); #endif
if (XRE_IsParentProcess()) {
GPUProcessManager::Shutdown();
VRProcessManager::Shutdown();
RDDProcessManager::Shutdown();
}
if (XRE_IsContentProcess()) {
gfx::VRManagerChild::ShutDown();
gfx::CanvasShutdownManager::Shutdown();
layers::CompositorManagerChild::Shutdown();
layers::ImageBridgeChild::ShutDown();
} elseif (XRE_IsParentProcess()) {
VideoBridgeParent::Shutdown();
RDDProcessManager::RDDProcessShutdown();
gfx::VRManagerChild::ShutDown();
gfx::CanvasShutdownManager::Shutdown();
layers::CompositorManagerChild::Shutdown();
layers::ImageBridgeChild::ShutDown(); // This could be running on either the Compositor thread, the Renderer // thread, or the dedicated CanvasRender thread, so we need to shutdown // before the former two.
gfx::CanvasRenderThread::Shutdown(); // This has to happen after shutting down the child protocols.
layers::CompositorThreadHolder::Shutdown();
RemoteTextureMap::Shutdown();
image::ImageMemoryReporter::ShutdownForWebRender(); // There is a case that RenderThread exists when UseWebRender() is // false. This could happen when WebRender was fallbacked to compositor. if (wr::RenderThread::Get()) {
wr::RenderThread::ShutDown();
Preferences::UnregisterCallback(WebRenderDebugPrefChangeCallback,
WR_DEBUG_PREF);
Preferences::UnregisterCallback(WebRendeProfilerUIPrefChangeCallback, "gfx.webrender.debug.profiler-ui");
Preferences::UnregisterCallback(
WebRenderBlobTileSizePrefChangeCallback,
nsDependentCString(
StaticPrefs::GetPrefName_gfx_webrender_blob_tile_size()));
} #ifdefined(XP_WIN)
widget::WinWindowOcclusionTracker::ShutDown(); #endif
} else { // TODO: There are other kind of processes and we should make sure gfx // stuff is either not created there or shut down properly.
}
}
void gfxPlatform::WillShutdown() { // Destoy these first in case they depend on backend-specific resources. // Otherwise, the backend's destructor would be called before the // base gfxPlatform destructor.
mScreenReferenceSurface = nullptr;
mScreenReferenceDrawTarget = nullptr;
// Always clear out the Skia font cache here, in case it is referencing any // SharedFTFaces that would otherwise outlive destruction of the FT_Library // that owns them.
SkGraphics::PurgeFontCache();
// The cairo folks think we should only clean up in debug builds, // but we're generally in the habit of trying to shut down as // cleanly as possible even in production code, so call this // cairo_debug_* function unconditionally. // // because cairo can assert and thus crash on shutdown, don't do this in // release builds #ifdef NS_FREE_PERMANENT_DATA
cairo_debug_reset_static_data(); #endif
}
/** * Record the backend that was used to construct the SourceSurface. * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair, * we check to make sure the DrawTarget's backend matches the backend * for the cached SourceSurface, and only use it if they match. This * can avoid expensive and unnecessary readbacks.
*/ struct SourceSurfaceUserData {
RefPtr<SourceSurface> mSrcSurface;
BackendType mBackendType;
};
if (userData) {
SourceSurfaceUserData* surf = static_cast<SourceSurfaceUserData*>(userData);
if (surf->mSrcSurface->IsValid() &&
surf->mBackendType == aTarget->GetBackendType()) {
RefPtr<SourceSurface> srcSurface(surf->mSrcSurface); return srcSurface.forget();
} // We can just continue here as when setting new user data the destroy // function will be called for the old user data.
}
SurfaceFormat format = aSurface->GetSurfaceFormat();
if (aTarget->GetBackendType() == BackendType::CAIRO) { // If we're going to be used with a CAIRO DrawTarget, then just create a // SourceSurfaceCairo since we don't know the underlying type of the CAIRO // DrawTarget and can't pick a better surface type. Doing this also avoids // readback of aSurface's surface into memory if, for example, aSurface // wraps an xlib cairo surface (which can be important to avoid a major // slowdown). // // We return here regardless of whether CreateSourceSurfaceFromNativeSurface // succeeds or not since we don't expect to be able to do any better below // if it fails. // // Note that the returned SourceSurfaceCairo holds a strong reference to // the cairo_surface_t* that it wraps, which essencially means it holds a // strong reference to aSurface since aSurface shares its // cairo_surface_t*'s reference count variable. As a result we can't cache // srcBuffer on aSurface (see below) since aSurface would then hold a // strong reference back to srcBuffer, creating a reference loop and a // memory leak. Not caching is fine since wrapping is cheap enough (no // copying) so we can just wrap again next time we're called. return Factory::CreateSourceSurfaceForCairoSurface(
aSurface->CairoSurface(), aSurface->GetSize(), format);
}
RefPtr<SourceSurface> srcBuffer;
// Currently no other DrawTarget types implement // CreateSourceSurfaceFromNativeSurface
if (!srcBuffer) { // If aSurface wraps data, we can create a SourceSurfaceRawData that wraps // the same data, then optimize it for aTarget:
RefPtr<DataSourceSurface> surf = GetWrappedDataSourceSurface(aSurface); if (surf) {
srcBuffer = aIsPlugin
? aTarget->OptimizeSourceSurfaceForUnknownAlpha(surf)
: aTarget->OptimizeSourceSurface(surf);
if (srcBuffer == surf) { // GetWrappedDataSourceSurface returns a SourceSurface that holds a // strong reference to aSurface since it wraps aSurface's data and // needs it to stay alive. As a result we can't cache srcBuffer on // aSurface (below) since aSurface would then hold a strong reference // back to srcBuffer, creating a reference loop and a memory leak. Not // caching is fine since wrapping is cheap enough (no copying) so we // can just wrap again next time we're called. // // Note that the check below doesn't catch this since srcBuffer will be // a SourceSurfaceRawData object (even if aSurface is not a // gfxImageSurface object), which is why we need this separate check. return srcBuffer.forget();
}
}
}
if (!srcBuffer) {
MOZ_ASSERT(aTarget->GetBackendType() != BackendType::CAIRO, "We already tried CreateSourceSurfaceFromNativeSurface with a " "DrawTargetCairo above"); // We've run out of performant options. We now try creating a SourceSurface // using a temporary DrawTargetCairo and then optimizing it to aTarget's // actual type. The CreateSourceSurfaceFromNativeSurface() call will // likely create a DataSourceSurface (possibly involving copying and/or // readback), and the OptimizeSourceSurface may well copy again and upload // to the GPU. So, while this code path is rarely hit, hitting it may be // very slow.
srcBuffer = Factory::CreateSourceSurfaceForCairoSurface(
aSurface->CairoSurface(), aSurface->GetSize(), format); if (srcBuffer) {
srcBuffer = aTarget->OptimizeSourceSurface(srcBuffer);
}
}
if (!srcBuffer) { return nullptr;
}
if ((srcBuffer->GetType() == SurfaceType::CAIRO && static_cast<SourceSurfaceCairo*>(srcBuffer.get())->GetSurface() ==
aSurface->CairoSurface()) ||
(srcBuffer->GetType() == SurfaceType::CAIRO_IMAGE && static_cast<DataSourceSurfaceCairo*>(srcBuffer.get())->GetSurface() ==
aSurface->CairoSurface())) { // See the "Note that the returned SourceSurfaceCairo..." comment above. return srcBuffer.forget();
}
// Add user data to aSurface so we can cache lookups in the future. auto* srcSurfUD = new SourceSurfaceUserData;
srcSurfUD->mBackendType = aTarget->GetBackendType();
srcSurfUD->mSrcSurface = srcBuffer;
aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy);
// If we wrapped the underlying data of aSurface, then we need to add user // data to make sure aSurface stays alive until we are done with the data. auto* srcSurfUD = new DependentSourceSurfaceUserData;
srcSurfUD->mSurface = aSurface;
result->AddUserData(&kThebesSurface, srcSurfUD, SourceSurfaceDestroyed);
return result.forget();
}
void gfxPlatform::PopulateScreenInfo() { // We're only going to set some gfxVars here, which is only possible from // the parent process. if (!XRE_IsParentProcess()) { return;
}
nsCOMPtr<nsIScreenManager> manager =
do_GetService("@mozilla.org/gfx/screenmanager;1");
MOZ_ASSERT(manager, "failed to get nsIScreenManager");
nsCOMPtr<nsIScreen> screen;
manager->GetPrimaryScreen(getter_AddRefs(screen)); if (!screen) { // This can happen in xpcshell, for instance return;
}
already_AddRefed<DrawTarget> gfxPlatform::CreateDrawTargetForBackend(
BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat) { // There is a bunch of knowledge in the gfxPlatform heirarchy about how to // create the best offscreen surface for the current system and situation. We // can easily take advantage of this for the Cairo backend, so that's what we // do. // mozilla::gfx::Factory can get away without having all this knowledge for // now, but this might need to change in the future (using // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all // backends). if (aBackend == BackendType::CAIRO) {
RefPtr<gfxASurface> surf =
CreateOffscreenSurface(aSize, SurfaceFormatToImageFormat(aFormat)); if (!surf || surf->CairoStatus()) { return nullptr;
} return CreateDrawTargetForSurface(surf, aSize);
} return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
}
BackendType backend = mFallbackCanvasBackend; // If we are using remote canvas we don't want to use acceleration in // canvas DrawTargets we are not remoting, so we always use the fallback // software one. if (!gfxPlatform::UseRemoteCanvas() ||
!gfxPlatform::IsBackendAccelerated(mPreferredCanvasBackend)) {
backend = mPreferredCanvasBackend;
}
#ifdef XP_WIN // On Windows, the fallback backend (Cairo) should use its image backend.
RefPtr<DrawTarget> target =
Factory::CreateDrawTarget(backend, aSize, aFormat); #else
RefPtr<DrawTarget> target =
CreateDrawTargetForBackend(backend, aSize, aFormat); #endif
if (target || mFallbackCanvasBackend == BackendType::NONE) { return target.forget();
}
#ifdef XP_WIN // On Windows, the fallback backend (Cairo) should use its image backend. return Factory::CreateDrawTarget(mFallbackCanvasBackend, aSize, aFormat); #else return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat); #endif
}
// We'd prefer this to take proper care and return a CaptureDT, but for the // moment since we can't and this means we're going to be drawing on the main // thread force it's initialization. See bug 1526045 and bug 1521368.
dt->ClearRect(gfx::Rect()); if (!dt->IsValid()) { return nullptr;
} return dt.forget();
}
nsAutoCString gfxPlatform::GetDefaultFontName( const nsACString& aLangGroup, const nsACString& aGenericFamily) { // To benefit from Return Value Optimization, all paths here must return // this one variable:
nsAutoCString result;
bool gfxPlatform::IsFontFormatSupported(
StyleFontFaceSourceFormatKeyword aFormatHint,
StyleFontFaceSourceTechFlags aTechFlags) { // By default, font resources are assumed to be supported; but if the format // hint or technology flags explicitly indicate something we don't support, // then return false. switch (aFormatHint) { case StyleFontFaceSourceFormatKeyword::None: break; case StyleFontFaceSourceFormatKeyword::Collection: returnfalse; case StyleFontFaceSourceFormatKeyword::Opentype: case StyleFontFaceSourceFormatKeyword::Truetype: break; case StyleFontFaceSourceFormatKeyword::EmbeddedOpentype: returnfalse; case StyleFontFaceSourceFormatKeyword::Svg: returnfalse; case StyleFontFaceSourceFormatKeyword::Woff: break; case StyleFontFaceSourceFormatKeyword::Woff2: break; case StyleFontFaceSourceFormatKeyword::Unknown:
--> --------------------
--> maximum size reached
--> --------------------
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.78Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.