diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index 47d8fbcaa8..7626a66824 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -272,7 +272,11 @@ Animation::GetAnimationOfProperty(nsCSSProperty aProperty) const for (size_t propIdx = 0, propEnd = mProperties.Length(); propIdx != propEnd; ++propIdx) { if (aProperty == mProperties[propIdx].mProperty) { - return &mProperties[propIdx]; + const AnimationProperty* result = &mProperties[propIdx]; + if (!result->mWinsInCascade) { + result = nullptr; + } + return result; } } return nullptr; diff --git a/dom/animation/Animation.h b/dom/animation/Animation.h index 84e4f29077..d98f892381 100644 --- a/dom/animation/Animation.h +++ b/dom/animation/Animation.h @@ -159,9 +159,12 @@ struct AnimationProperty // then use this to decide whether to apply the style both in the CSS // cascade and for OMTA. // - // FIXME (bug 847287): For CSS Animations, which are overridden by - // !important rules in the cascade, we actually determine this from - // the CSS cascade computations, and then use it for OMTA. + // For CSS Animations, which are overridden by !important rules in the + // cascade, we actually determine this from the CSS cascade + // computations, and then use it for OMTA. + // **NOTE**: For CSS animations, we only bother setting mWinsInCascade + // accurately for properties that we can animate on the compositor. + // For other properties, we make it always be true. bool mWinsInCascade; InfallibleTArray mSegments; diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index b46d6f051a..757e4ca3e9 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -193,6 +193,7 @@ WebGLContextOptions::WebGLContextOptions() , premultipliedAlpha(true) , antialias(true) , preserveDrawingBuffer(false) + , failIfMajorPerformanceCaveat(false) { // Set default alpha state based on preference. if (Preferences::GetBool("webgl.default-no-alpha", false)) @@ -436,6 +437,7 @@ WebGLContext::SetContextOptions(JSContext* cx, JS::Handle options) newOpts.premultipliedAlpha = attributes.mPremultipliedAlpha; newOpts.antialias = attributes.mAntialias; newOpts.preserveDrawingBuffer = attributes.mPreserveDrawingBuffer; + newOpts.failIfMajorPerformanceCaveat = attributes.mFailIfMajorPerformanceCaveat; if (attributes.mAlpha.WasPassed()) newOpts.alpha = attributes.mAlpha.Value(); @@ -503,6 +505,30 @@ IsFeatureInBlacklist(const nsCOMPtr& gfxInfo, int32_t feature) return status != nsIGfxInfo::FEATURE_STATUS_OK; } +static bool +HasAcceleratedLayers(const nsCOMPtr& gfxInfo) +{ + int32_t status; + + gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status); + if (status) + return true; + gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS, &status); + if (status) + return true; + gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS, &status); + if (status) + return true; + gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &status); + if (status) + return true; + gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status); + if (status) + return true; + + return false; +} + static already_AddRefed CreateHeadlessNativeGL(bool forceEnabled, const nsCOMPtr& gfxInfo, bool requireCompatProfile, WebGLContext* webgl) @@ -572,7 +598,6 @@ CreateHeadlessEGL(bool forceEnabled, bool requireCompatProfile, return gl.forget(); } - static already_AddRefed CreateHeadlessGL(bool forceEnabled, const nsCOMPtr& gfxInfo, WebGLContext* webgl) @@ -871,6 +896,18 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight) return NS_ERROR_FAILURE; } + nsCOMPtr gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); + bool failIfMajorPerformanceCaveat = + !gfxPrefs::WebGLDisableFailIfMajorPerformanceCaveat() && + !HasAcceleratedLayers(gfxInfo); + if (failIfMajorPerformanceCaveat) { + Nullable contextAttributes; + this->GetContextAttributes(contextAttributes); + if (contextAttributes.Value().mFailIfMajorPerformanceCaveat) { + return NS_ERROR_FAILURE; + } + } + // Alright, now let's start trying. bool forceEnabled = Preferences::GetBool("webgl.force-enabled", false); @@ -1251,6 +1288,7 @@ WebGLContext::GetContextAttributes(Nullable& retval result.mAntialias = mOptions.antialias; result.mPremultipliedAlpha = mOptions.premultipliedAlpha; result.mPreserveDrawingBuffer = mOptions.preserveDrawingBuffer; + result.mFailIfMajorPerformanceCaveat = mOptions.failIfMajorPerformanceCaveat; } /* [noscript] DOMString mozGetUnderlyingParamString(in GLenum pname); */ diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index 3378555108..872e1f8c46 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -130,6 +130,7 @@ struct WebGLContextOptions bool premultipliedAlpha; bool antialias; bool preserveDrawingBuffer; + bool failIfMajorPerformanceCaveat; }; // From WebGLContextUtils diff --git a/dom/webidl/WebGLRenderingContext.webidl b/dom/webidl/WebGLRenderingContext.webidl index 7321528edf..043e65e645 100644 --- a/dom/webidl/WebGLRenderingContext.webidl +++ b/dom/webidl/WebGLRenderingContext.webidl @@ -41,6 +41,7 @@ dictionary WebGLContextAttributes { boolean antialias = true; boolean premultipliedAlpha = true; boolean preserveDrawingBuffer = false; + boolean failIfMajorPerformanceCaveat = false; }; interface WebGLBuffer { diff --git a/gfx/gl/GLContextProviderCGL.mm b/gfx/gl/GLContextProviderCGL.mm index a0468907c9..b3b1e93437 100644 --- a/gfx/gl/GLContextProviderCGL.mm +++ b/gfx/gl/GLContextProviderCGL.mm @@ -9,10 +9,9 @@ #include "nsDebug.h" #include "nsIWidget.h" #include -#include "gfxPrefs.h" #include "gfxFailure.h" +#include "gfxPrefs.h" #include "prenv.h" -#include "mozilla/Preferences.h" #include "GeckoProfiler.h" #include "mozilla/gfx/MacIOSurface.h" @@ -185,7 +184,11 @@ static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered[] = { }; static const NSOpenGLPixelFormatAttribute kAttribs_offscreen[] = { - NSOpenGLPFAPixelBuffer, + 0 +}; + +static const NSOpenGLPixelFormatAttribute kAttribs_offscreen_accel[] = { + NSOpenGLPFAAccelerated, 0 }; @@ -202,8 +205,10 @@ CreateWithFormat(const NSOpenGLPixelFormatAttribute* attribs) { NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; - if (!format) + if (!format) { + NS_WARNING("Failed to create NSOpenGLPixelFormat."); return nullptr; + } NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nullptr]; @@ -265,9 +270,14 @@ CreateOffscreenFBOContext(bool requireCompatProfile) } if (!context) { profile = ContextProfile::OpenGLCompatibility; - context = CreateWithFormat(kAttribs_offscreen); + + if (gfxPrefs::RequireHardwareGL()) + context = CreateWithFormat(kAttribs_offscreen_accel); + else + context = CreateWithFormat(kAttribs_offscreen); } if (!context) { + NS_WARNING("Failed to create NSOpenGLContext."); return nullptr; } @@ -286,8 +296,10 @@ GLContextProviderCGL::CreateHeadless(bool requireCompatProfile) if (!gl) return nullptr; - if (!gl->Init()) + if (!gl->Init()) { + NS_WARNING("Failed during Init."); return nullptr; + } return gl.forget(); } @@ -298,8 +310,10 @@ GLContextProviderCGL::CreateOffscreen(const gfxIntSize& size, bool requireCompatProfile) { nsRefPtr glContext = CreateHeadless(requireCompatProfile); - if (!glContext->InitOffscreen(ToIntSize(size), caps)) + if (!glContext->InitOffscreen(ToIntSize(size), caps)) { + NS_WARNING("Failed during InitOffscreen."); return nullptr; + } return glContext.forget(); } diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 486324176b..c9fc09cf27 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1108,6 +1108,7 @@ public: // Call AddAnimation to add a new animation to this layer from layout code. // Caller must fill in all the properties of the returned animation. + // A later animation overrides an earlier one. Animation* AddAnimation(); // ClearAnimations clears animations on this layer. void ClearAnimations(); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 82b72d2f0b..3c1ed281d0 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -440,7 +440,8 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint) bool activeAnimations = false; - for (uint32_t i = animations.Length(); i-- !=0; ) { + // Process in order, since later animations override earlier ones. + for (size_t i = 0, iEnd = animations.Length(); i < iEnd; ++i) { Animation& animation = animations[i]; AnimData& animData = animationData[i]; diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index 4ef956acce..8775892440 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -137,22 +137,22 @@ private: DECL_GFX_PREF(Live, "apz.allow_checkerboarding", APZAllowCheckerboarding, bool, true); DECL_GFX_PREF(Live, "apz.asyncscroll.throttle", APZAsyncScrollThrottleTime, int32_t, 100); DECL_GFX_PREF(Live, "apz.asyncscroll.timeout", APZAsyncScrollTimeout, int32_t, 300); - DECL_GFX_PREF(Live, "apz.axis_lock.mode", APZAxisLockMode, int32_t, 0); - DECL_GFX_PREF(Live, "apz.axis_lock.lock_angle", APZAxisLockAngle, float, float(M_PI / 6.0) /* 30 degrees */); - DECL_GFX_PREF(Live, "apz.axis_lock.breakout_threshold", APZAxisBreakoutThreshold, float, 1.0f / 32.0f); DECL_GFX_PREF(Live, "apz.axis_lock.breakout_angle", APZAxisBreakoutAngle, float, float(M_PI / 8.0) /* 22.5 degrees */); + DECL_GFX_PREF(Live, "apz.axis_lock.breakout_threshold", APZAxisBreakoutThreshold, float, 1.0f / 32.0f); DECL_GFX_PREF(Live, "apz.axis_lock.direct_pan_angle", APZAllowedDirectPanAngle, float, float(M_PI / 3.0) /* 60 degrees */); + DECL_GFX_PREF(Live, "apz.axis_lock.lock_angle", APZAxisLockAngle, float, float(M_PI / 6.0) /* 30 degrees */); + DECL_GFX_PREF(Live, "apz.axis_lock.mode", APZAxisLockMode, int32_t, 0); DECL_GFX_PREF(Live, "apz.content_response_timeout", APZContentResponseTimeout, int32_t, 300); DECL_GFX_PREF(Live, "apz.cross_slide.enabled", APZCrossSlideEnabled, bool, false); DECL_GFX_PREF(Live, "apz.danger_zone_x", APZDangerZoneX, int32_t, 50); DECL_GFX_PREF(Live, "apz.danger_zone_y", APZDangerZoneY, int32_t, 100); DECL_GFX_PREF(Live, "apz.enlarge_displayport_when_clipped", APZEnlargeDisplayPortWhenClipped, bool, false); - DECL_GFX_PREF(Live, "apz.fling_accel_interval_ms", APZFlingAccelInterval, int32_t, 500); DECL_GFX_PREF(Live, "apz.fling_accel_base_mult", APZFlingAccelBaseMultiplier, float, 1.0f); + DECL_GFX_PREF(Live, "apz.fling_accel_interval_ms", APZFlingAccelInterval, int32_t, 500); DECL_GFX_PREF(Live, "apz.fling_accel_supplemental_mult", APZFlingAccelSupplementalMultiplier, float, 1.0f); DECL_GFX_PREF(Once, "apz.fling_curve_function_x1", APZCurveFunctionX1, float, 0.0f); - DECL_GFX_PREF(Once, "apz.fling_curve_function_y1", APZCurveFunctionY1, float, 0.0f); DECL_GFX_PREF(Once, "apz.fling_curve_function_x2", APZCurveFunctionX2, float, 1.0f); + DECL_GFX_PREF(Once, "apz.fling_curve_function_y1", APZCurveFunctionY1, float, 0.0f); DECL_GFX_PREF(Once, "apz.fling_curve_function_y2", APZCurveFunctionY2, float, 1.0f); DECL_GFX_PREF(Live, "apz.fling_curve_threshold_inches_per_ms", APZCurveThreshold, float, -1.0f); DECL_GFX_PREF(Once, "apz.fling_friction", APZFlingFriction, float, 0.002f); @@ -165,11 +165,11 @@ private: DECL_GFX_PREF(Live, "apz.num_paint_duration_samples", APZNumPaintDurationSamples, int32_t, 3); DECL_GFX_PREF(Live, "apz.overscroll.enabled", APZOverscrollEnabled, bool, false); DECL_GFX_PREF(Live, "apz.overscroll.min_pan_distance_ratio", APZMinPanDistanceRatio, float, 1.0f); - DECL_GFX_PREF(Live, "apz.overscroll.stretch_factor", APZOverscrollStretchFactor, float, 0.5f); - DECL_GFX_PREF(Live, "apz.overscroll.spring_stiffness", APZOverscrollSpringStiffness, float, 0.001f); DECL_GFX_PREF(Live, "apz.overscroll.spring_friction", APZOverscrollSpringFriction, float, 0.015f); + DECL_GFX_PREF(Live, "apz.overscroll.spring_stiffness", APZOverscrollSpringStiffness, float, 0.001f); DECL_GFX_PREF(Live, "apz.overscroll.stop_distance_threshold", APZOverscrollStopDistanceThreshold, float, 5.0f); DECL_GFX_PREF(Live, "apz.overscroll.stop_velocity_threshold", APZOverscrollStopVelocityThreshold, float, 0.01f); + DECL_GFX_PREF(Live, "apz.overscroll.stretch_factor", APZOverscrollStretchFactor, float, 0.5f); DECL_GFX_PREF(Live, "apz.pan_repaint_interval", APZPanRepaintInterval, int32_t, 250); DECL_GFX_PREF(Live, "apz.printtree", APZPrintTree, bool, false); DECL_GFX_PREF(Live, "apz.smooth_scroll_repaint_interval", APZSmoothScrollRepaintInterval, int32_t, 75); @@ -184,17 +184,20 @@ private: DECL_GFX_PREF(Live, "apz.y_stationary_size_multiplier", APZYStationarySizeMultiplier, float, 3.5f); DECL_GFX_PREF(Live, "apz.zoom_animation_duration_ms", APZZoomAnimationDuration, int32_t, 250); + DECL_GFX_PREF(Once, "dom.vr.enabled", VREnabled, bool, false); + DECL_GFX_PREF(Once, "dom.vr.add-test-devices", VRAddTestDevices, int32_t, 1); + DECL_GFX_PREF(Once, "gfx.android.rgb16.force", AndroidRGB16Force, bool, false); #if defined(ANDROID) DECL_GFX_PREF(Once, "gfx.apitrace.enabled", UseApitrace, bool, false); #endif + DECL_GFX_PREF(Live, "gfx.canvas.auto_accelerate.min_calls", CanvasAutoAccelerateMinCalls, int32_t, 4); DECL_GFX_PREF(Live, "gfx.canvas.auto_accelerate.min_frames", CanvasAutoAccelerateMinFrames, int32_t, 30); DECL_GFX_PREF(Live, "gfx.canvas.auto_accelerate.min_seconds", CanvasAutoAccelerateMinSeconds, float, 5.0f); - DECL_GFX_PREF(Live, "gfx.canvas.auto_accelerate.min_calls", CanvasAutoAccelerateMinCalls, int32_t, 4); DECL_GFX_PREF(Live, "gfx.canvas.azure.accelerated", CanvasAzureAccelerated, bool, false); - DECL_GFX_PREF(Once, "gfx.canvas.skiagl.dynamic-cache", CanvasSkiaGLDynamicCache, bool, false); - DECL_GFX_PREF(Once, "gfx.canvas.skiagl.cache-size", CanvasSkiaGLCacheSize, int32_t, 96); DECL_GFX_PREF(Once, "gfx.canvas.skiagl.cache-items", CanvasSkiaGLCacheItems, int32_t, 256); + DECL_GFX_PREF(Once, "gfx.canvas.skiagl.cache-size", CanvasSkiaGLCacheSize, int32_t, 96); + DECL_GFX_PREF(Once, "gfx.canvas.skiagl.dynamic-cache", CanvasSkiaGLDynamicCache, bool, false); DECL_GFX_PREF(Live, "gfx.color_management.enablev4", CMSEnableV4, bool, false); DECL_GFX_PREF(Live, "gfx.color_management.mode", CMSMode, int32_t,-1); @@ -204,7 +207,8 @@ private: DECL_GFX_PREF(Once, "gfx.direct2d.disabled", Direct2DDisabled, bool, false); DECL_GFX_PREF(Once, "gfx.direct2d.force-enabled", Direct2DForceEnabled, bool, false); DECL_GFX_PREF(Live, "gfx.direct2d.use1_1", Direct2DUse1_1, bool, false); - DECL_GFX_PREF(Live, "gfx.direct2d.allow-fallback", Direct2DAllowFallback, bool, false); + DECL_GFX_PREF(Live, "gfx.direct2d.allow1_0", Direct2DAllow1_0, bool, false); + DECL_GFX_PREF(Live, "gfx.draw-color-bars", CompositorDrawColorBars, bool, false); DECL_GFX_PREF(Live, "gfx.gralloc.fence-with-readpixels", GrallocFenceWithReadPixels, bool, false); DECL_GFX_PREF(Live, "gfx.layerscope.enabled", LayerScopeEnabled, bool, false); DECL_GFX_PREF(Live, "gfx.layerscope.port", LayerScopePort, int32_t, 23456); @@ -214,28 +218,28 @@ private: DECL_GFX_PREF(Once, "gfx.max-alloc-size", MaxAllocSize, int32_t, (int32_t)500000000); DECL_GFX_PREF(Once, "gfx.max-texture-size", MaxTextureSize, int32_t, (int32_t)32767); DECL_GFX_PREF(Live, "gfx.perf-warnings.enabled", PerfWarnings, bool, false); - DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs", WorkAroundDriverBugs, bool, true); + DECL_GFX_PREF(Once, "gfx.touch.resample", TouchResampling, bool, false); - DECL_GFX_PREF(Live, "gfx.draw-color-bars", CompositorDrawColorBars, bool, false); + // These times should be in milliseconds + DECL_GFX_PREF(Once, "gfx.touch.resample.delay-threshold", TouchResampleVsyncDelayThreshold, int32_t, 20); + DECL_GFX_PREF(Once, "gfx.touch.resample.max-predict", TouchResampleMaxPredict, int32_t, 8); + DECL_GFX_PREF(Once, "gfx.touch.resample.old-touch-threshold",TouchResampleOldTouchThreshold, int32_t, 17); + DECL_GFX_PREF(Once, "gfx.touch.resample.vsync-adjust", TouchVsyncSampleAdjust, int32_t, 5); - // Use vsync events generated by hardware - DECL_GFX_PREF(Once, "gfx.vsync.hw-vsync.enabled", HardwareVsyncEnabled, bool, false); DECL_GFX_PREF(Once, "gfx.vsync.compositor", VsyncAlignedCompositor, bool, false); - DECL_GFX_PREF(Once, "gfx.vsync.refreshdriver", VsyncAlignedRefreshDriver, bool, false); // On b2g, in really bad cases, I've seen up to 80 ms delays between touch events and the main thread // processing them. So 80 ms / 16 = 5 vsync events. Double it up just to be on the safe side, so 10. DECL_GFX_PREF(Once, "gfx.vsync.compositor.unobserve-count", CompositorUnobserveCount, int32_t, 10); - DECL_GFX_PREF(Once, "gfx.touch.resample", TouchResampling, bool, false); - // These times should be in milliseconds - DECL_GFX_PREF(Once, "gfx.touch.resample.max-predict", TouchResampleMaxPredict, int32_t, 8); - DECL_GFX_PREF(Once, "gfx.touch.resample.vsync-adjust", TouchVsyncSampleAdjust, int32_t, 5); - DECL_GFX_PREF(Once, "gfx.touch.resample.delay-threshold", TouchResampleVsyncDelayThreshold, int32_t, 20); - DECL_GFX_PREF(Once, "gfx.touch.resample.old-touch-threshold",TouchResampleOldTouchThreshold, int32_t, 17); + // Use vsync events generated by hardware + DECL_GFX_PREF(Once, "gfx.vsync.hw-vsync.enabled", HardwareVsyncEnabled, bool, false); + DECL_GFX_PREF(Once, "gfx.vsync.refreshdriver", VsyncAlignedRefreshDriver, bool, false); + DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs", WorkAroundDriverBugs, bool, true); DECL_GFX_PREF(Live, "gl.msaa-level", MSAALevel, uint32_t, 2); + DECL_GFX_PREF(Live, "gl.require-hardware", RequireHardwareGL, bool, false); - DECL_GFX_PREF(Once, "image.cache.timeweight", ImageCacheTimeWeight, int32_t, 500); DECL_GFX_PREF(Once, "image.cache.size", ImageCacheSize, int32_t, 5*1024*1024); + DECL_GFX_PREF(Once, "image.cache.timeweight", ImageCacheTimeWeight, int32_t, 500); DECL_GFX_PREF(Live, "image.downscale-during-decode.enabled", ImageDownscaleDuringDecodeEnabled, bool, true); DECL_GFX_PREF(Live, "image.high_quality_downscaling.enabled", ImageHQDownscalingEnabled, bool, false); DECL_GFX_PREF(Live, "image.high_quality_downscaling.min_factor", ImageHQDownscalingMinFactor, uint32_t, 1000); @@ -256,9 +260,9 @@ private: DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram", FPSPrintHistogram, bool, false); DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false); DECL_GFX_PREF(Once, "layers.acceleration.force-enabled", LayersAccelerationForceEnabled, bool, false); + DECL_GFX_PREF(Once, "layers.async-pan-zoom.enabled", AsyncPanZoomEnabled, bool, false); DECL_GFX_PREF(Once, "layers.async-video.enabled", AsyncVideoEnabled, bool, true); DECL_GFX_PREF(Once, "layers.async-video-oop.enabled", AsyncVideoOOPEnabled, bool, true); - DECL_GFX_PREF(Once, "layers.async-pan-zoom.enabled", AsyncPanZoomEnabled, bool, false); DECL_GFX_PREF(Live, "layers.bench.enabled", LayersBenchEnabled, bool, false); DECL_GFX_PREF(Once, "layers.bufferrotation.enabled", BufferRotationEnabled, bool, true); #ifdef MOZ_GFX_OPTIMIZE_MOBILE @@ -270,83 +274,72 @@ private: // preference value, defaulting to true. DECL_GFX_PREF(Once, "layers.componentalpha.enabled", ComponentAlphaEnabled, bool, true); #endif + DECL_GFX_PREF(Once, "layers.d3d11.disable-warp", LayersD3D11DisableWARP, bool, false); + DECL_GFX_PREF(Once, "layers.d3d11.force-warp", LayersD3D11ForceWARP, bool, false); DECL_GFX_PREF(Live, "layers.draw-bigimage-borders", DrawBigImageBorders, bool, false); DECL_GFX_PREF(Live, "layers.draw-borders", DrawLayerBorders, bool, false); DECL_GFX_PREF(Live, "layers.draw-tile-borders", DrawTileBorders, bool, false); - DECL_GFX_PREF(Live, "layers.flash-borders", FlashLayerBorders, bool, false); DECL_GFX_PREF(Live, "layers.draw-layer-info", DrawLayerInfo, bool, false); DECL_GFX_PREF(Live, "layers.dump", LayersDump, bool, false); DECL_GFX_PREF(Live, "layers.dump-texture", LayersDumpTexture, bool, false); #ifdef MOZ_DUMP_PAINTING - DECL_GFX_PREF(Live, "layers.dump-decision", LayersDumpDecision, bool, false); DECL_GFX_PREF(Live, "layers.dump-client-layers", DumpClientLayers, bool, false); + DECL_GFX_PREF(Live, "layers.dump-decision", LayersDumpDecision, bool, false); DECL_GFX_PREF(Live, "layers.dump-host-layers", DumpHostLayers, bool, false); #endif - DECL_GFX_PREF(Live, "layers.transaction.warning-ms", LayerTransactionWarning, uint32_t, 200); // 0 is "no change" for contrast, positive values increase it, negative values // decrease it until we hit mid gray at -1 contrast, after that it gets weird. DECL_GFX_PREF(Live, "layers.effect.contrast", LayersEffectContrast, float, 0.0f); DECL_GFX_PREF(Live, "layers.effect.grayscale", LayersEffectGrayscale, bool, false); DECL_GFX_PREF(Live, "layers.effect.invert", LayersEffectInvert, bool, false); - DECL_GFX_PREF(Once, "layers.enable-tiles", LayersTilesEnabled, bool, false); - DECL_GFX_PREF(Once, "layers.tiled-drawtarget.enabled", TiledDrawTargetEnabled, bool, false); + DECL_GFX_PREF(Live, "layers.flash-borders", FlashLayerBorders, bool, false); + DECL_GFX_PREF(Once, "layers.force-shmem-tiles", ForceShmemTiles, bool, false); + DECL_GFX_PREF(Live, "layers.frame-counter", DrawFrameCounter, bool, false); + DECL_GFX_PREF(Once, "layers.gralloc.disable", DisableGralloc, bool, false); + DECL_GFX_PREF(Live, "layers.low-precision-buffer", UseLowPrecisionBuffer, bool, false); + DECL_GFX_PREF(Live, "layers.low-precision-opacity", LowPrecisionOpacity, float, 1.0f); + DECL_GFX_PREF(Live, "layers.low-precision-resolution", LowPrecisionResolution, float, 0.25f); + DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.enabled", LayersOffMainThreadCompositionEnabled, bool, false); + DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-enabled", LayersOffMainThreadCompositionForceEnabled, bool, false); + DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1); + DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.testing.enabled", LayersOffMainThreadCompositionTestingEnabled, bool, false); + DECL_GFX_PREF(Live, "layers.orientation.sync.timeout", OrientationSyncMillis, uint32_t, (uint32_t)0); + DECL_GFX_PREF(Once, "layers.overzealous-gralloc-unlocking", OverzealousGrallocUnlocking, bool, false); + DECL_GFX_PREF(Once, "layers.prefer-d3d9", LayersPreferD3D9, bool, false); + DECL_GFX_PREF(Once, "layers.prefer-opengl", LayersPreferOpenGL, bool, false); + DECL_GFX_PREF(Live, "layers.progressive-paint", ProgressivePaintDoNotUseDirectly, bool, false); + DECL_GFX_PREF(Once, "layers.stereo-video.enabled", StereoVideoEnabled, bool, false); + // We allow for configurable and rectangular tile size to avoid wasting memory on devices whose // screen size does not align nicely to the default tile size. Although layers can be any size, // they are often the same size as the screen, especially for width. DECL_GFX_PREF(Once, "layers.tile-width", LayersTileWidth, int32_t, 256); DECL_GFX_PREF(Once, "layers.tile-height", LayersTileHeight, int32_t, 256); - DECL_GFX_PREF(Once, "layers.tiles.adjust", LayersTilesAdjust, bool, true); DECL_GFX_PREF(Once, "layers.tile-max-pool-size", LayersTileMaxPoolSize, uint32_t, (uint32_t)50); DECL_GFX_PREF(Once, "layers.tile-shrink-pool-timeout", LayersTileShrinkPoolTimeout, uint32_t, (uint32_t)1000); - DECL_GFX_PREF(Once, "layers.overzealous-gralloc-unlocking", OverzealousGrallocUnlocking, bool, false); - DECL_GFX_PREF(Once, "layers.force-shmem-tiles", ForceShmemTiles, bool, false); - DECL_GFX_PREF(Live, "layers.frame-counter", DrawFrameCounter, bool, false); - DECL_GFX_PREF(Live, "layers.low-precision-buffer", UseLowPrecisionBuffer, bool, false); - DECL_GFX_PREF(Live, "layers.low-precision-resolution", LowPrecisionResolution, float, 0.25f); - DECL_GFX_PREF(Live, "layers.low-precision-opacity", LowPrecisionOpacity, float, 1.0f); - DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.enabled", LayersOffMainThreadCompositionEnabled, bool, false); - DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1); - DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-enabled", LayersOffMainThreadCompositionForceEnabled, bool, false); - DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.testing.enabled", LayersOffMainThreadCompositionTestingEnabled, bool, false); - DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces", UseImageOffscreenSurfaces, bool, false); - DECL_GFX_PREF(Live, "layers.orientation.sync.timeout", OrientationSyncMillis, uint32_t, (uint32_t)0); - DECL_GFX_PREF(Once, "layers.d3d11.disable-warp", LayersD3D11DisableWARP, bool, false); - DECL_GFX_PREF(Once, "layers.d3d11.force-warp", LayersD3D11ForceWARP, bool, false); - DECL_GFX_PREF(Once, "layers.prefer-d3d9", LayersPreferD3D9, bool, false); - DECL_GFX_PREF(Once, "layers.prefer-opengl", LayersPreferOpenGL, bool, false); - DECL_GFX_PREF(Live, "layers.progressive-paint", ProgressivePaintDoNotUseDirectly, bool, false); + DECL_GFX_PREF(Once, "layers.tiled-drawtarget.enabled", TiledDrawTargetEnabled, bool, false); + DECL_GFX_PREF(Once, "layers.tiles.adjust", LayersTilesAdjust, bool, true); + DECL_GFX_PREF(Live, "layers.transaction.warning-ms", LayerTransactionWarning, uint32_t, 200); DECL_GFX_PREF(Once, "layers.uniformity-info", UniformityInfo, bool, false); - DECL_GFX_PREF(Once, "layers.gralloc.disable", DisableGralloc, bool, false); + DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces", UseImageOffscreenSurfaces, bool, false); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled", ScrollBehaviorEnabled, bool, false); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.spring-constant", ScrollBehaviorSpringConstant, float, 250.0f); - DECL_GFX_PREF(Live, "layout.css.scroll-snap.prediction-sensitivity", ScrollSnapPredictionSensitivity, float, 0.750f); DECL_GFX_PREF(Live, "layout.css.scroll-snap.prediction-max-velocity", ScrollSnapPredictionMaxVelocity, int32_t, 2000); + DECL_GFX_PREF(Live, "layout.css.scroll-snap.prediction-sensitivity", ScrollSnapPredictionSensitivity, float, 0.750f); DECL_GFX_PREF(Once, "layout.css.touch_action.enabled", TouchActionEnabled, bool, false); - DECL_GFX_PREF(Once, "layout.frame_rate", LayoutFrameRate, int32_t, -1); DECL_GFX_PREF(Live, "layout.display-list.dump", LayoutDumpDisplayList, bool, false); DECL_GFX_PREF(Live, "layout.event-regions.enabled", LayoutEventRegionsEnabled, bool, false); + DECL_GFX_PREF(Once, "layout.frame_rate", LayoutFrameRate, int32_t, -1); DECL_GFX_PREF(Once, "layout.paint_rects_separately", LayoutPaintRectsSeparately, bool, true); #ifdef MOZ_JXR DECL_GFX_PREF(Live, "media.jxr.enabled", MediaJXREnabled, bool, false); DECL_GFX_PREF(Live, "media.jxr.workaround_alphaplane_bug", MediaJXRWorkaroundAlphaplaneBug, bool, false); #endif - DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false); - - DECL_GFX_PREF(Live, "ui.click_hold_context_menus.delay", UiClickHoldContextMenusDelay, int32_t, 500); - - DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false); - DECL_GFX_PREF(Once, "webgl.angle.try-d3d11", WebGLANGLETryD3D11, bool, false); - DECL_GFX_PREF(Once, "webgl.angle.force-d3d11", WebGLANGLEForceD3D11, bool, false); - - DECL_GFX_PREF(Once, "layers.stereo-video.enabled", StereoVideoEnabled, bool, false); - - DECL_GFX_PREF(Once, "dom.vr.enabled", VREnabled, bool, false); - DECL_GFX_PREF(Once, "dom.vr.add-test-devices", VRAddTestDevices, int32_t, 1); // This and code dependent on it should be removed once containerless scrolling looks stable. DECL_GFX_PREF(Once, "layout.scroll.root-frame-containers", LayoutUseContainersForRootFrames, bool, true); @@ -354,6 +347,19 @@ private: // This affects whether events will be routed through APZ or not. DECL_GFX_PREF(Once, "mousewheel.system_scroll_override_on_root_content.enabled", MouseWheelHasScrollDeltaOverride, bool, false); + + DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false); + DECL_GFX_PREF(Live, "ui.click_hold_context_menus.delay", UiClickHoldContextMenusDelay, int32_t, 500); + DECL_GFX_PREF(Once, "webgl.angle.try-d3d11", WebGLANGLETryD3D11, bool, false); + DECL_GFX_PREF(Once, "webgl.angle.force-d3d11", WebGLANGLEForceD3D11, bool, false); + DECL_GFX_PREF(Live, "webgl.disable-fail-if-major-performance-caveat", + WebGLDisableFailIfMajorPerformanceCaveat, bool, false); + DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false); + + // WARNING: + // Please make sure that you've added your new preference to the list above in alphabetical order. + // Please do not just append it to the end of the list. + public: // Manage the singleton: static gfxPrefs& GetSingleton() diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 0629d85e04..436edb7993 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -650,9 +650,7 @@ gfxWindowsPlatform::CreateDevice(nsRefPtr &adapter1, void gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce) { - // Check if fallback to unsupported D2D version is allowed when - // the Direct2D 1.1 feature set isn't available. - if (!Factory::SupportsD2D1() && !gfxPrefs::Direct2DAllowFallback()) { + if ((!Factory::SupportsD2D1() || !gfxPrefs::Direct2DUse1_1()) && !gfxPrefs::Direct2DAllow1_0()) { return; } diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 07edf2cf57..6f0e365dca 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -413,6 +413,7 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR), "inconsistent property flags"); + // Add from first to last (since last overrides) for (size_t playerIdx = 0; playerIdx < aPlayers.Length(); playerIdx++) { AnimationPlayer* player = aPlayers[playerIdx]; if (!player->IsPlaying()) { @@ -426,17 +427,17 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, continue; } - if (!property->mWinsInCascade) { - // We have an animation or transition, but it isn't actually - // winning in the CSS cascade, so we don't want to send it to the - // compositor. - // I believe that anything that changes mWinsInCascade should - // trigger this code again, either because of a restyle that - // changes the properties in question, or because of the - // main-thread style update that results when an animation stops - // filling. - continue; - } + // Note that if mWinsInCascade on property was false, + // GetAnimationOfProperty returns null instead. + // This is what we want, since if we have an animation or transition + // that isn't actually winning in the CSS cascade, we don't want to + // send it to the compositor. + // I believe that anything that changes mWinsInCascade should + // trigger this code again, either because of a restyle that changes + // the properties in question, or because of the main-thread style + // update that results when an animation stops being in effect. + MOZ_ASSERT(property->mWinsInCascade, + "GetAnimationOfProperty already tested mWinsInCascade"); // Don't add animations that are pending when their corresponding // refresh driver is under test control. This is because any pending @@ -501,11 +502,9 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer, return; } AnimationPlayerCollection* transitions = - nsTransitionManager::GetAnimationsForCompositor(content, aProperty, - GetCompositorAnimationOptions::NotifyActiveLayerTracker); + nsTransitionManager::GetAnimationsForCompositor(content, aProperty); AnimationPlayerCollection* animations = - nsAnimationManager::GetAnimationsForCompositor(content, aProperty, - GetCompositorAnimationOptions::NotifyActiveLayerTracker); + nsAnimationManager::GetAnimationsForCompositor(content, aProperty); if (!animations && !transitions) { return; @@ -562,6 +561,8 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer, data = null_t(); } + // When both are running, animations override transitions. We want + // to add the ones that override last. if (transitions) { AddAnimationsForProperty(aFrame, aProperty, transitions->mPlayers, aLayer, data, pending); diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 70e5705dc4..b5876d7807 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -120,9 +120,8 @@ CommonAnimationManager::CheckNeedsRefresh() AnimationPlayerCollection* CommonAnimationManager::GetAnimationsForCompositor(nsIContent* aContent, - nsIAtom* aElementProperty, - nsCSSProperty aProperty, - GetCompositorAnimationOptions aFlags) + nsIAtom* aElementProperty, + nsCSSProperty aProperty) { if (!aContent->MayHaveAnimations()) return nullptr; @@ -137,23 +136,7 @@ CommonAnimationManager::GetAnimationsForCompositor(nsIContent* aContent, return nullptr; } - if (!(aFlags & GetCompositorAnimationOptions::NotifyActiveLayerTracker)) { - return collection; - } - // This animation can be done on the compositor. - // Mark the frame as active, in case we are able to throttle this animation. - nsIFrame* frame = nsLayoutUtils::GetStyleFrame(collection->mElement); - if (frame) { - const auto& info = sLayerAnimationInfo; - for (size_t i = 0; i < ArrayLength(info); i++) { - if (aProperty == info[i].mProperty) { - ActiveLayerTracker::NotifyAnimated(frame, aProperty); - break; - } - } - } - return collection; } @@ -416,6 +399,21 @@ CommonAnimationManager::GetAnimationRule(mozilla::dom::Element* aElement, nsDisplayItem::TYPE_OPACITY, nsChangeHint_UpdateOpacityLayer } }; +/* static */ const CommonAnimationManager::LayerAnimationRecord* +CommonAnimationManager::LayerAnimationRecordFor(nsCSSProperty aProperty) +{ + MOZ_ASSERT(nsCSSProps::PropHasFlags(aProperty, + CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR), + "unexpected property"); + const auto& info = sLayerAnimationInfo; + for (size_t i = 0; i < ArrayLength(info); ++i) { + if (aProperty == info[i].mProperty) { + return &info[i]; + } + } + return nullptr; +} + #ifdef DEBUG /* static */ void CommonAnimationManager::Initialize() @@ -653,6 +651,30 @@ AnimationPlayerCollection::CanPerformOnCompositorThread( return true; } +void +AnimationPlayerCollection::PostUpdateLayerAnimations() +{ + nsCSSPropertySet propsHandled; + for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { + const auto& properties = mPlayers[playerIdx]->GetSource()->Properties(); + for (size_t propIdx = properties.Length(); propIdx-- != 0; ) { + nsCSSProperty prop = properties[propIdx].mProperty; + if (nsCSSProps::PropHasFlags(prop, + CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR) && + !propsHandled.HasProperty(prop)) { + propsHandled.AddProperty(prop); + nsChangeHint changeHint = css::CommonAnimationManager:: + LayerAnimationRecordFor(prop)->mChangeHint; + dom::Element* element = GetElementToRestyle(); + if (element) { + mManager->mPresContext->RestyleManager()-> + PostRestyleEvent(element, nsRestyleHint(0), changeHint); + } + } + } + } +} + bool AnimationPlayerCollection::HasAnimationOfProperty( nsCSSProperty aProperty) const @@ -754,6 +776,12 @@ AnimationPlayerCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime, return; } + if (!mStyleRuleRefreshTime.IsNull() && + mStyleRuleRefreshTime == aRefreshTime) { + // mStyleRule may be null and valid, if we have no style to apply. + return; + } + // If we're performing animations on the compositor thread, then we can skip // most of the work in this method. But even if we are throttled, then we // have to do the work if an animation is ending in order to get correct end @@ -773,35 +801,28 @@ AnimationPlayerCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime, return; } - // mStyleRule may be null and valid, if we have no style to apply. - if (mStyleRuleRefreshTime.IsNull() || - mStyleRuleRefreshTime != aRefreshTime) { - mStyleRuleRefreshTime = aRefreshTime; - mStyleRule = nullptr; - // We'll set mNeedsRefreshes to true below in all cases where we need them. - mNeedsRefreshes = false; + if (mManager->IsAnimationManager()) { + // Update cascade results before updating the style rule, since the + // cascade results can influence the style rule. + static_cast(mManager)->MaybeUpdateCascadeResults(this); + } - // If multiple animations specify behavior for the same property the - // animation which occurs last in the value of animation-name wins. - // As a result, we iterate from last animation to first and, if a - // property has already been set, we don't leave it. - nsCSSPropertySet properties; + mStyleRuleRefreshTime = aRefreshTime; + mStyleRule = nullptr; + // We'll set mNeedsRefreshes to true below in all cases where we need them. + mNeedsRefreshes = false; - for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { - mPlayers[playerIdx]->ComposeStyle(mStyleRule, properties, - mNeedsRefreshes); - } + // If multiple animations specify behavior for the same property the + // animation which occurs last in the value of animation-name wins. + // As a result, we iterate from last animation to first and, if a + // property has already been set, we don't leave it. + nsCSSPropertySet properties; + + for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) { + mPlayers[playerIdx]->ComposeStyle(mStyleRule, properties, mNeedsRefreshes); } mManager->CheckNeedsRefresh(); - - // If one of our animations just started or stopped filling, we need - // to notify the transition manager. This does the notification a bit - // more than necessary, but it's easier than doing it exactly. - if (mManager->IsAnimationManager()) { - mManager->mPresContext->TransitionManager()-> - UpdateCascadeResultsWithAnimations(this); - } } bool diff --git a/layout/style/AnimationCommon.h b/layout/style/AnimationCommon.h index 7afc1ef6c8..b074b544ac 100644 --- a/layout/style/AnimationCommon.h +++ b/layout/style/AnimationCommon.h @@ -35,14 +35,6 @@ namespace mozilla { class RestyleTracker; struct AnimationPlayerCollection; -// Options to set when fetching animations to run on the compositor. -enum class GetCompositorAnimationOptions { - // When fetching compositor animations, if there are any such animations, - // also let the ActiveLayerTracker know at the same time. - NotifyActiveLayerTracker = 1 << 0 -}; -MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(GetCompositorAnimationOptions) - namespace css { bool IsGeometricProperty(nsCSSProperty aProperty); @@ -77,6 +69,9 @@ public: static void Initialize(); #endif + // NOTE: This can return null after Disconnect(). + nsPresContext* PresContext() const { return mPresContext; } + /** * Notify the manager that the pres context is going away. */ @@ -136,6 +131,12 @@ protected: public: static const LayerAnimationRecord sLayerAnimationInfo[kLayerRecords]; + // Will return non-null for any property with the + // CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR flag; should only be called + // on such properties. + static const LayerAnimationRecord* + LayerAnimationRecordFor(nsCSSProperty aProperty); + protected: virtual ~CommonAnimationManager(); @@ -160,8 +161,7 @@ protected: static AnimationPlayerCollection* GetAnimationsForCompositor(nsIContent* aContent, nsIAtom* aElementProperty, - nsCSSProperty aProperty, - GetCompositorAnimationOptions aFlags); + nsCSSProperty aProperty); PRCList mElementCollections; nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect) @@ -302,6 +302,9 @@ struct AnimationPlayerCollection : public PRCList // (This is useful for determining whether throttle the animation // (suppress main-thread style updates).) bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const; + + void PostUpdateLayerAnimations(); + bool HasAnimationOfProperty(nsCSSProperty aProperty) const; bool IsForElement() const { // rather than for a pseudo-element diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index fae937afda..f2bce7b5b8 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -222,6 +222,32 @@ nsAnimationManager::QueueEvents(AnimationPlayerCollection* aCollection, } } +void +nsAnimationManager::MaybeUpdateCascadeResults(AnimationPlayerCollection* aCollection) +{ + for (size_t playerIdx = aCollection->mPlayers.Length(); playerIdx-- != 0; ) { + CSSAnimationPlayer* player = + aCollection->mPlayers[playerIdx]->AsCSSAnimationPlayer(); + + if (player->HasInEffectSource() != player->mInEffectForCascadeResults) { + // Update our own cascade results. + mozilla::dom::Element* element = aCollection->GetElementToRestyle(); + if (element) { + nsIFrame* frame = element->GetPrimaryFrame(); + if (frame) { + UpdateCascadeResults(frame->StyleContext(), aCollection); + } + } + + // Notify the transition manager, whose results might depend on ours. + mPresContext->TransitionManager()-> + UpdateCascadeResultsWithAnimations(aCollection); + + return; + } + } +} + /* virtual */ size_t nsAnimationManager::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { @@ -391,6 +417,8 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, newPlayers[newPlayerIdx]->Cancel(); } + UpdateCascadeResults(aStyleContext, collection); + TimeStamp refreshTime = mPresContext->RefreshDriver()->MostRecentRefresh(); UpdateStyleAndEvents(collection, refreshTime, EnsureStyleRule_IsNotThrottled); @@ -706,6 +734,119 @@ nsAnimationManager::BuildSegment(InfallibleTArray& return true; } +/* static */ void +nsAnimationManager::UpdateCascadeResults( + nsStyleContext* aStyleContext, + AnimationPlayerCollection* aElementAnimations) +{ + /* + * Figure out which properties we need to examine. + */ + + // size of 2 since we only currently have 2 properties we animate on + // the compositor + nsAutoTArray propertiesToTrack; + + { + nsCSSPropertySet propertiesToTrackAsSet; + + for (size_t playerIdx = aElementAnimations->mPlayers.Length(); + playerIdx-- != 0; ) { + const AnimationPlayer* player = aElementAnimations->mPlayers[playerIdx]; + const Animation* anim = player->GetSource(); + if (!anim) { + continue; + } + + for (size_t propIdx = 0, propEnd = anim->Properties().Length(); + propIdx != propEnd; ++propIdx) { + const AnimationProperty& prop = anim->Properties()[propIdx]; + // We only bother setting mWinsInCascade for properties that we + // can animate on the compositor. + if (nsCSSProps::PropHasFlags(prop.mProperty, + CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR)) { + if (!propertiesToTrackAsSet.HasProperty(prop.mProperty)) { + propertiesToTrack.AppendElement(prop.mProperty); + propertiesToTrackAsSet.AddProperty(prop.mProperty); + } + } + } + } + } + + /* + * Determine whether those properties are set in things that + * override animations. + */ + + nsCSSPropertySet propertiesOverridden; + nsRuleNode::ComputePropertiesOverridingAnimation(propertiesToTrack, + aStyleContext, + propertiesOverridden); + + /* + * Set mWinsInCascade based both on what is overridden at levels + * higher than animations and based on one animation overriding + * another. + * + * We iterate from the last animation to the first, just like we do + * when calling ComposeStyle from + * AnimationPlayerCollection::EnsureStyleRuleFor. Later animations + * override earlier ones, so we add properties to the set of + * overridden properties as we encounter them, if the animation is + * currently in effect. + */ + + bool changed = false; + for (size_t playerIdx = aElementAnimations->mPlayers.Length(); + playerIdx-- != 0; ) { + CSSAnimationPlayer* player = + aElementAnimations->mPlayers[playerIdx]->AsCSSAnimationPlayer(); + Animation* anim = player->GetSource(); + + player->mInEffectForCascadeResults = player->HasInEffectSource(); + + if (!anim) { + continue; + } + + for (size_t propIdx = 0, propEnd = anim->Properties().Length(); + propIdx != propEnd; ++propIdx) { + AnimationProperty& prop = anim->Properties()[propIdx]; + // We only bother setting mWinsInCascade for properties that we + // can animate on the compositor. + if (nsCSSProps::PropHasFlags(prop.mProperty, + CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR)) { + bool newWinsInCascade = + !propertiesOverridden.HasProperty(prop.mProperty); + if (newWinsInCascade != prop.mWinsInCascade) { + changed = true; + } + prop.mWinsInCascade = newWinsInCascade; + + if (prop.mWinsInCascade && player->mInEffectForCascadeResults) { + // This animation is in effect right now, so it overrides + // earlier animations. (For animations that aren't in effect, + // we set mWinsInCascade as though they were, but they don't + // suppress animations lower in the cascade.) + propertiesOverridden.AddProperty(prop.mProperty); + } + } + } + } + + if (changed) { + nsPresContext* presContext = aElementAnimations->mManager->PresContext(); + presContext->RestyleManager()->IncrementAnimationGeneration(); + aElementAnimations->UpdateAnimationGeneration(presContext); + aElementAnimations->PostUpdateLayerAnimations(); + + // Invalidate our style rule. + aElementAnimations->mNeedsRefreshes = true; + aElementAnimations->mStyleRuleRefreshTime = TimeStamp(); + } +} + /* virtual */ void nsAnimationManager::WillRefresh(mozilla::TimeStamp aTime) { diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 46297d5356..bd62b8e020 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -80,6 +80,13 @@ public: void QueueEvents(EventArray& aEventsToDispatch); + // Is this animation currently in effect for the purposes of computing + // mWinsInCascade. (In general, this can be computed from the timing + // function. This boolean remembers the state as of the last time we + // called UpdateCascadeResults so we know if it changes and we need to + // call UpdateCascadeResults again.) + bool mInEffectForCascadeResults; + protected: virtual ~CSSAnimationPlayer() { } virtual css::CommonAnimationManager* GetAnimationManager() const override; @@ -159,12 +166,10 @@ public: } static mozilla::AnimationPlayerCollection* - GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty, - mozilla::GetCompositorAnimationOptions aFlags - = mozilla::GetCompositorAnimationOptions(0)) + GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty) { return mozilla::css::CommonAnimationManager::GetAnimationsForCompositor( - aContent, nsGkAtoms::animationsProperty, aProperty, aFlags); + aContent, nsGkAtoms::animationsProperty, aProperty); } void UpdateStyleAndEvents(mozilla::AnimationPlayerCollection* aEA, @@ -173,6 +178,9 @@ public: void QueueEvents(mozilla::AnimationPlayerCollection* aEA, mozilla::EventArray &aEventsToDispatch); + void MaybeUpdateCascadeResults(mozilla::AnimationPlayerCollection* + aCollection); + // nsIStyleRuleProcessor (parts) virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_MUST_OVERRIDE override; @@ -239,6 +247,10 @@ private: mozilla::css::Declaration* aFromDeclaration, float aToKey, nsStyleContext* aToContext); + static void UpdateCascadeResults(nsStyleContext* aStyleContext, + mozilla::AnimationPlayerCollection* + aElementAnimations); + // The guts of DispatchEvents void DoDispatchEvents(); diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 82024afd6a..83ba7604a0 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -47,6 +47,7 @@ #include "CSSVariableResolver.h" #include "nsCSSParser.h" #include "CounterStyleManager.h" +#include "nsCSSPropertySet.h" #if defined(_MSC_VER) || defined(__MINGW32__) #include @@ -9695,6 +9696,89 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext, return false; } +/* static */ void +nsRuleNode::ComputePropertiesOverridingAnimation( + const nsTArray& aProperties, + nsStyleContext* aStyleContext, + nsCSSPropertySet& aPropertiesOverridden) +{ + /* + * Set up an nsRuleData with all the structs needed for all of the + * properties in aProperties. + */ + uint32_t structBits = 0; + size_t nprops = 0; + size_t offsets[nsStyleStructID_Length]; + for (size_t propIdx = 0, propEnd = aProperties.Length(); + propIdx < propEnd; ++propIdx) { + nsCSSProperty prop = aProperties[propIdx]; + nsStyleStructID sid = nsCSSProps::kSIDTable[prop]; + uint32_t bit = nsCachedStyleData::GetBitForSID(sid); + if (!(structBits & bit)) { + structBits |= bit; + offsets[sid] = nprops; + nprops += nsCSSProps::PropertyCountInStruct(sid); + } + } + + void* dataStorage = alloca(nprops * sizeof(nsCSSValue)); + AutoCSSValueArray dataArray(dataStorage, nprops); + + // We're relying on the use of |aStyleContext| not mutating it! + nsRuleData ruleData(structBits, dataArray.get(), + aStyleContext->PresContext(), aStyleContext); + for (nsStyleStructID sid = nsStyleStructID(0); + sid < nsStyleStructID_Length; sid = nsStyleStructID(sid + 1)) { + if (structBits & nsCachedStyleData::GetBitForSID(sid)) { + ruleData.mValueOffsets[sid] = offsets[sid]; + } + } + + /* + * Actually walk up the rule tree until we're someplace less + * specific than animations. + */ + for (nsRuleNode* ruleNode = aStyleContext->RuleNode(); ruleNode; + ruleNode = ruleNode->GetParent()) { + nsIStyleRule *rule = ruleNode->GetRule(); + if (rule) { + ruleData.mLevel = ruleNode->GetLevel(); + ruleData.mIsImportantRule = ruleNode->IsImportantRule(); + + // Transitions are the only non-!important level overriding + // animations in the cascade ordering. They also don't actually + // override animations, since transitions are suppressed when both + // are present. And since we might not have called + // UpdateCascadeResults (which updates when they are suppressed + // due to the presence of animations for the same element and + // property) for transitions yet (which will make their + // MapRuleInfoInto skip the properties that are currently + // animating), we should skip them explicitly. + if (ruleData.mLevel == nsStyleSet::eTransitionSheet) { + continue; + } + + if (!ruleData.mIsImportantRule) { + // We're now equal to or less than the animation level; stop. + break; + } + + rule->MapRuleInfoInto(&ruleData); + } + } + + /* + * Fill in which properties were overridden. + */ + for (size_t propIdx = 0, propEnd = aProperties.Length(); + propIdx < propEnd; ++propIdx) { + nsCSSProperty prop = aProperties[propIdx]; + if (ruleData.ValueFor(prop)->GetUnit() != eCSSUnit_Null) { + aPropertiesOverridden.AddProperty(prop); + } + } +} + /* static */ bool nsRuleNode::ComputeColor(const nsCSSValue& aValue, nsPresContext* aPresContext, diff --git a/layout/style/nsRuleNode.h b/layout/style/nsRuleNode.h index 6665410c27..b7c6ac2ae3 100644 --- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -18,7 +18,7 @@ class nsStyleContext; struct nsRuleData; class nsIStyleRule; struct nsCSSValueList; - +class nsCSSPropertySet; class nsCSSValue; struct nsCSSRect; @@ -738,6 +738,17 @@ public: uint32_t ruleTypeMask, bool aAuthorColorsAllowed); + /** + * Fill in to aPropertiesOverridden all of the properties in aProperties + * that, for this rule node, have a declaration that is higher than the + * animation level in the CSS Cascade. + */ + static void + ComputePropertiesOverridingAnimation( + const nsTArray& aProperties, + nsStyleContext* aStyleContext, + nsCSSPropertySet& aPropertiesOverridden); + // Expose this so media queries can use it static nscoord CalcLengthWithInitialFont(nsPresContext* aPresContext, const nsCSSValue& aValue); diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index b57a4e4b5a..7c17b8832e 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -615,7 +615,7 @@ nsTransitionManager::UpdateCascadeResultsWithTransitions( void nsTransitionManager::UpdateCascadeResultsWithAnimations( - const AnimationPlayerCollection* aAnimations) + AnimationPlayerCollection* aAnimations) { AnimationPlayerCollection* transitions = mPresContext->TransitionManager()-> @@ -641,7 +641,7 @@ nsTransitionManager::UpdateCascadeResultsWithAnimationsToBeDestroyed( void nsTransitionManager::UpdateCascadeResults( AnimationPlayerCollection* aTransitions, - const AnimationPlayerCollection* aAnimations) + AnimationPlayerCollection* aAnimations) { if (!aTransitions) { // Nothing to do. @@ -656,8 +656,15 @@ nsTransitionManager::UpdateCascadeResults( // http://dev.w3.org/csswg/css-transitions/#application says that // transitions do not apply when the same property has a CSS Animation // on that element (even though animations are lower in the cascade). - if (aAnimations && aAnimations->mStyleRule) { - aAnimations->mStyleRule->AddPropertiesToSet(propertiesUsed); + if (aAnimations) { + TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh(); + // Passing EnsureStyleRule_IsThrottled is OK since we will + // unthrottle when animations are finishing. + aAnimations->EnsureStyleRuleFor(now, EnsureStyleRule_IsThrottled); + + if (aAnimations->mStyleRule) { + aAnimations->mStyleRule->AddPropertiesToSet(propertiesUsed); + } } // Since we should never have more than one transition for the same @@ -685,7 +692,9 @@ nsTransitionManager::UpdateCascadeResults( } if (changed) { + mPresContext->RestyleManager()->IncrementAnimationGeneration(); aTransitions->UpdateAnimationGeneration(mPresContext); + aTransitions->PostUpdateLayerAnimations(); // Invalidate our style rule. aTransitions->mStyleRuleRefreshTime = TimeStamp(); diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index ad4c3a3fc2..347e5806cd 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -104,12 +104,10 @@ public: typedef mozilla::AnimationPlayerCollection AnimationPlayerCollection; static AnimationPlayerCollection* - GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty, - mozilla::GetCompositorAnimationOptions aFlags - = mozilla::GetCompositorAnimationOptions(0)) + GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty) { return mozilla::css::CommonAnimationManager::GetAnimationsForCompositor( - aContent, nsGkAtoms::transitionsProperty, aProperty, aFlags); + aContent, nsGkAtoms::transitionsProperty, aProperty); } /** @@ -133,11 +131,11 @@ public: void UpdateCascadeResultsWithTransitions( AnimationPlayerCollection* aTransitions); void UpdateCascadeResultsWithAnimations( - const AnimationPlayerCollection* aAnimations); + AnimationPlayerCollection* aAnimations); void UpdateCascadeResultsWithAnimationsToBeDestroyed( const AnimationPlayerCollection* aAnimations); void UpdateCascadeResults(AnimationPlayerCollection* aTransitions, - const AnimationPlayerCollection* aAnimations); + AnimationPlayerCollection* aAnimations); void SetInAnimationOnlyStyleUpdate(bool aInAnimationOnlyUpdate) { mInAnimationOnlyStyleUpdate = aInAnimationOnlyUpdate; diff --git a/layout/style/test/test_animations_omta.html b/layout/style/test/test_animations_omta.html index fe11d601e3..2f147c173e 100644 --- a/layout/style/test/test_animations_omta.html +++ b/layout/style/test/test_animations_omta.html @@ -430,48 +430,42 @@ addAsyncAnimTest(function *() { yield waitForPaintsFlushed(); omta_is("transform", { tx: 32 }, RunningOn.Compositor, "anim2 + anim1 + anim2, translate at 2s"); - // Bug 980769 - todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.1", - "anim2 + anim1 + anim2, opacity at 2s"); + is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.1", + "anim2 + anim1 + anim2, opacity at 2s"); // drop one of the anim2, and list anim3 as well, which animates // the same property as anim2 gDiv.style.animation = "anim1 linear 10s, anim2 linear 20s, anim3 linear 10s"; yield waitForPaintsFlushed(); omta_is("transform", { tx: 32 }, RunningOn.Compositor, "anim1 + anim2 + anim3, translate at 2s"); - // Bug 980769 - todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0", - "anim1 + anim2 + anim3, opacity at 2s"); + is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0", + "anim1 + anim2 + anim3, opacity at 2s"); advance_clock(1000); omta_is("transform", { tx: 48 }, RunningOn.Compositor, "anim1 + anim2 + anim3, translate at 3s"); - // Bug 980769 - todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.1", - "anim1 + anim2 + anim3, opacity at 3s"); + is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.1", + "anim1 + anim2 + anim3, opacity at 3s"); // now swap the anim3 and anim2 order gDiv.style.animation = "anim1 linear 10s, anim3 linear 10s, anim2 linear 20s"; yield waitForPaintsFlushed(); omta_is("transform", { tx: 48 }, RunningOn.Compositor, "anim1 + anim3 + anim2, translate at 3s"); - // Bug 980769 - todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.15", - "anim1 + anim3 + anim2, opacity at 3s"); + is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.15", + "anim1 + anim3 + anim2, opacity at 3s"); advance_clock(2000); // (unlike test_animations.html, we seek 2s forwards here // since at 4s anim2 and anim3 produce the same result so // we can't tell which won.) omta_is("transform", { tx: 80 }, RunningOn.Compositor, "anim1 + anim3 + anim2, translate at 5s"); - // Bug 980769 - todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.25", - "anim1 + anim3 + anim2, opacity at 5s"); + is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.25", + "anim1 + anim3 + anim2, opacity at 5s"); // swap anim3 and anim2 back gDiv.style.animation = "anim1 linear 10s, anim2 linear 20s, anim3 linear 10s"; yield waitForPaintsFlushed(); omta_is("transform", { tx: 80 }, RunningOn.Compositor, "anim1 + anim2 + anim3, translate at 5s"); - // Bug 980769 - todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.3", - "anim1 + anim2 + anim3, opacity at 5s"); + is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.3", + "anim1 + anim2 + anim3, opacity at 5s"); // seek past end of anim1 advance_clock(5100); yield waitForPaints(); @@ -494,9 +488,8 @@ addAsyncAnimTest(function *() { yield waitForPaintsFlushed(); omta_is("transform", { tx: 82 }, RunningOn.Compositor, "anim1 + anim2 + anim3, translate at 11s with fill mode"); - // Bug 980769 - We should get 0.9 but instead - todo_is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.9", - "anim1 + anim2 + anim3, opacity at 11s"); + is(SpecialPowers.DOMWindowUtils.getOMTAStyle(gDiv, "opacity"), "0.9", + "anim1 + anim2 + anim3, opacity at 11s"); done_div(); }); @@ -1527,9 +1520,8 @@ addAsyncAnimTest(function *() { new_div("animation: always_fifty 1s linear infinite; " + "transform: translate(200px) ! important;"); yield waitForPaintsFlushed(); - // Bug 847287 - off main thread animations don't cascade correctly - omta_todo_is("transform", { tx: 200 }, RunningOn.TodoMainThread, - "important author rules override animations"); + omta_is("transform", { tx: 200 }, RunningOn.MainThread, + "important author rules override animations"); done_div(); }); @@ -1721,11 +1713,9 @@ addAsyncAnimTest(function *() { "animation-timing-function: linear; " + "animation-delay: -250ms, -250ms, -750ms, -500ms;"); yield waitForPaintsFlushed(); - // Bug 980769 - off main thread animations incorrectly handle multiple - // animations of the same property and element - omta_todo_is("opacity", 0.75, RunningOn.Compositor, - "animation-name list length is the length that matters, " + - "and the last occurrence of a name wins"); + omta_is("opacity", 0.75, RunningOn.Compositor, + "animation-name list length is the length that matters, " + + "and the last occurrence of a name wins"); omta_is("transform", { ty: 25 }, RunningOn.Compositor, "animation-name list length is the length that matters"); done_div(); @@ -2108,35 +2098,35 @@ addAsyncAnimTest(function *() { new_div("animation: anim2 1s linear forwards; opacity: 0.5 ! important"); yield waitForPaintsFlushed(); - omta_todo_is("opacity", 0.5, RunningOn.TodoMainThread, + omta_is("opacity", 0.5, RunningOn.MainThread, "opacity overriding animation at start (0s)"); advance_clock(750); - omta_todo_is("opacity", 0.5, RunningOn.TodoMainThread, + omta_is("opacity", 0.5, RunningOn.MainThread, "opacity overriding animation while running (750ms)"); advance_clock(1000); - omta_todo_is("opacity", 0.5, RunningOn.TodoMainThread, + omta_is("opacity", 0.5, RunningOn.MainThread, "opacity overriding animation while filling (1750ms)"); done_div(); new_div("animation: anim2 1s linear; opacity: 0.5 ! important"); yield waitForPaintsFlushed(); - omta_todo_is("opacity", 0.5, RunningOn.TodoMainThread, + omta_is("opacity", 0.5, RunningOn.MainThread, "opacity overriding animation at start (0s)"); advance_clock(750); - omta_todo_is("opacity", 0.5, RunningOn.TodoMainThread, + omta_is("opacity", 0.5, RunningOn.MainThread, "opacity overriding animation while running (750ms)"); advance_clock(1000); - omta_todo_is("opacity", 0.5, RunningOn.TodoMainThread, + omta_is("opacity", 0.5, RunningOn.MainThread, "opacity overriding animation after complete (1750ms)"); done_div(); // One animation overriding another, and then not. new_div("animation: anim2 1s linear, anim3 500ms linear reverse"); yield waitForPaintsFlushed(); - omta_todo_is("opacity", 1, RunningOn.Compositor, + omta_is("opacity", 1, RunningOn.Compositor, "anim3 overriding anim2 at start (0s)"); advance_clock(400); - omta_todo_is("opacity", 0.2, RunningOn.Compositor, + omta_is("opacity", 0.2, RunningOn.Compositor, "anim3 overriding anim2 at 400ms"); advance_clock(200); // Wait for paints because we're resending animations to the @@ -2158,7 +2148,7 @@ addAsyncAnimTest(function *() { "anim2 at 300ms"); gDiv.style.animation = "anim2 1s steps(8, end), anim3 500ms steps(4, end)"; yield waitForPaintsFlushed(); - omta_todo_is("opacity", 0, RunningOn.Compositor, + omta_is("opacity", 0, RunningOn.Compositor, "anim3 overriding anim2 at 300ms"); advance_clock(475); omta_is("opacity", 0.75, RunningOn.Compositor, @@ -2186,7 +2176,7 @@ addAsyncAnimTest(function *() { "anim2 at 300ms"); gDiv.style.animation = "anim2 1s steps(8, end), anim3 500ms steps(4, end)"; yield waitForPaintsFlushed(); - omta_todo_is("opacity", 0, RunningOn.Compositor, + omta_is("opacity", 0, RunningOn.Compositor, "anim3 overriding anim2 at 300ms"); advance_clock(475); omta_is("opacity", 0.75, RunningOn.Compositor, diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 526d67e3e8..cc8258b758 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4238,6 +4238,9 @@ pref("webgl.enable-draft-extensions", false); pref("webgl.enable-privileged-extensions", false); pref("webgl.bypass-shader-validation", false); pref("webgl.enable-prototype-webgl2", false); +pref("webgl.disable-fail-if-major-performance-caveat", false); +pref("gl.require-hardware", false); + #ifdef XP_WIN pref("webgl.angle.try-d3d11", true); pref("webgl.angle.force-d3d11", false); @@ -4379,7 +4382,6 @@ pref("gfx.xrender.enabled",true); // Whether to disable the automatic detection and use of direct2d. pref("gfx.direct2d.disabled", false); pref("gfx.direct2d.use1_1", true); -pref("gfx.direct2d.allow-fallback", false); // Whether to attempt to enable Direct2D regardless of automatic detection or // blacklisting