summaryrefslogtreecommitdiffstats
path: root/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'gfx')
-rw-r--r--gfx/2d/2D.h5
-rw-r--r--gfx/2d/DrawEventRecorder.cpp4
-rw-r--r--gfx/2d/DrawEventRecorder.h4
-rw-r--r--gfx/2d/DrawTargetSkia.cpp2
-rw-r--r--gfx/2d/Factory.cpp34
-rw-r--r--gfx/2d/MacIOSurface.cpp67
-rw-r--r--gfx/2d/MacIOSurface.h31
-rw-r--r--gfx/2d/ScaledFontMac.cpp6
-rw-r--r--gfx/2d/moz.build6
-rw-r--r--gfx/angle/moz.build5
-rw-r--r--gfx/angle/targets/angle_gpu_info_util/moz.build4
-rw-r--r--gfx/angle/targets/angle_image_util/moz.build4
-rw-r--r--gfx/angle/targets/libEGL/moz.build5
-rw-r--r--gfx/angle/targets/libGLESv2/moz.build2
-rw-r--r--gfx/angle/targets/preprocessor/moz.build4
-rw-r--r--gfx/angle/targets/translator/moz.build1
-rwxr-xr-xgfx/angle/update-angle.py14
-rw-r--r--gfx/config/gfxVars.h4
-rw-r--r--gfx/gl/GLBlitHelper.cpp5
-rw-r--r--gfx/gl/GLContext.cpp17
-rw-r--r--gfx/gl/GLContextEAGL.h19
-rw-r--r--gfx/gl/GLContextProvider.h8
-rw-r--r--gfx/gl/GLContextProviderEAGL.mm74
-rw-r--r--gfx/gl/GLTypes.h7
-rw-r--r--gfx/gl/SharedSurface.cpp14
-rw-r--r--gfx/gl/SharedSurfaceIO.cpp11
-rw-r--r--gfx/gl/moz.build1
-rw-r--r--gfx/ipc/CanvasManagerChild.cpp65
-rw-r--r--gfx/ipc/CanvasManagerChild.h8
-rw-r--r--gfx/ipc/CanvasShutdownManager.cpp179
-rw-r--r--gfx/ipc/CanvasShutdownManager.h57
-rw-r--r--gfx/ipc/GPUParent.cpp13
-rw-r--r--gfx/ipc/GPUParent.h3
-rw-r--r--gfx/ipc/GPUProcessManager.cpp60
-rw-r--r--gfx/ipc/GPUProcessManager.h19
-rw-r--r--gfx/ipc/PGPU.ipdl3
-rw-r--r--gfx/ipc/moz.build2
-rw-r--r--gfx/layers/BuildConstants.h7
-rw-r--r--gfx/layers/CanvasDrawEventRecorder.cpp114
-rw-r--r--gfx/layers/CanvasDrawEventRecorder.h24
-rw-r--r--gfx/layers/FrameMetrics.cpp10
-rw-r--r--gfx/layers/FrameMetrics.h12
-rw-r--r--gfx/layers/ImageContainer.cpp4
-rw-r--r--gfx/layers/ImageContainer.h14
-rw-r--r--gfx/layers/NativeLayerCA.h22
-rw-r--r--gfx/layers/NativeLayerCA.mm212
-rw-r--r--gfx/layers/PersistentBufferProvider.cpp7
-rw-r--r--gfx/layers/RemoteTextureMap.cpp100
-rw-r--r--gfx/layers/RemoteTextureMap.h8
-rw-r--r--gfx/layers/SurfacePool.h2
-rw-r--r--gfx/layers/SurfacePoolCA.h2
-rw-r--r--gfx/layers/SurfacePoolCA.mm21
-rw-r--r--gfx/layers/apz/src/APZCTreeManager.cpp56
-rw-r--r--gfx/layers/apz/src/APZCTreeManager.h9
-rw-r--r--gfx/layers/apz/src/APZUpdater.cpp30
-rw-r--r--gfx/layers/apz/src/AsyncPanZoomController.cpp46
-rw-r--r--gfx/layers/apz/src/AsyncPanZoomController.h2
-rw-r--r--gfx/layers/apz/src/AutoscrollAnimation.cpp2
-rw-r--r--gfx/layers/apz/src/GenericScrollAnimation.cpp9
-rw-r--r--gfx/layers/apz/src/GestureEventListener.cpp87
-rw-r--r--gfx/layers/apz/src/GestureEventListener.h3
-rw-r--r--gfx/layers/apz/test/gtest/TestGestureDetector.cpp236
-rw-r--r--gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js14
-rw-r--r--gfx/layers/apz/test/mochitest/apz_test_utils.js4
-rw-r--r--gfx/layers/apz/test/mochitest/browser.toml8
-rw-r--r--gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js2
-rw-r--r--gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js1
-rw-r--r--gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_basic_scrollend.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_browser_test_utils.js2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1346632.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1414336.html6
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html4
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1695598.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_content_response_timeout.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_displayport_expiry.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_fullscreen.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html4
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_fixed.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html4
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_key_scroll.html4
-rw-r--r--gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_touch_action_regions.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_zoomed_pan.html4
-rw-r--r--gfx/layers/apz/test/mochitest/test_smoothness.html2
-rw-r--r--gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html4
-rw-r--r--gfx/layers/apz/test/reftest/reftest.list18
-rw-r--r--gfx/layers/apz/testutil/APZTestData.h6
-rw-r--r--gfx/layers/apz/util/APZCCallbackHelper.cpp3
-rw-r--r--gfx/layers/apz/util/APZEventState.cpp2
-rw-r--r--gfx/layers/client/TextureClient.cpp10
-rw-r--r--gfx/layers/client/TextureRecorded.cpp5
-rw-r--r--gfx/layers/client/TextureRecorded.h3
-rw-r--r--gfx/layers/ipc/CanvasChild.cpp164
-rw-r--r--gfx/layers/ipc/CanvasChild.h20
-rw-r--r--gfx/layers/ipc/CanvasTranslator.cpp32
-rw-r--r--gfx/layers/ipc/CanvasTranslator.h3
-rw-r--r--gfx/layers/ipc/CompositorManagerChild.cpp11
-rw-r--r--gfx/layers/ipc/LayersMessageUtils.h2
-rw-r--r--gfx/layers/ipc/PCanvas.ipdl6
-rw-r--r--gfx/layers/ipc/VideoBridgeParent.cpp5
-rw-r--r--gfx/layers/moz.build4
-rw-r--r--gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp1
-rw-r--r--gfx/layers/wr/AsyncImagePipelineManager.cpp3
-rw-r--r--gfx/layers/wr/WebRenderBridgeParent.cpp10
-rw-r--r--gfx/layers/wr/WebRenderImageHost.cpp13
-rw-r--r--gfx/layers/wr/WebRenderScrollData.cpp16
-rw-r--r--gfx/layers/wr/WebRenderScrollData.h13
-rw-r--r--gfx/ots/src/ots.h13
-rw-r--r--gfx/ots/src/stat.cc21
-rw-r--r--gfx/qcms/Cargo.toml3
-rw-r--r--gfx/qcms/build.rs7
-rw-r--r--gfx/qcms/src/iccread.rs4
-rw-r--r--gfx/qcms/src/lib.rs6
-rw-r--r--gfx/qcms/src/transform.rs179
-rw-r--r--gfx/qcms/src/transform_avx.rs22
-rw-r--r--gfx/qcms/src/transform_neon.rs14
-rw-r--r--gfx/qcms/src/transform_sse2.rs12
-rw-r--r--gfx/qcms/src/transform_util.rs3
-rw-r--r--gfx/skia/skia/src/ports/SkTypeface_mac_ct.cpp4
-rw-r--r--gfx/src/DriverCrashGuard.cpp4
-rw-r--r--gfx/tests/browser/browser_native_font_cache_macos.js10
-rw-r--r--gfx/tests/browser/browser_windowless_troubleshoot_crash.js9
-rw-r--r--gfx/tests/chrome/test_device_reset.html2
-rw-r--r--gfx/tests/crashtests/1701975-1.html20
-rw-r--r--gfx/tests/crashtests/306902-1.xml14
-rw-r--r--gfx/tests/crashtests/385289-1.xhtml30
-rw-r--r--gfx/tests/crashtests/410728-1.xml14
-rw-r--r--gfx/tests/crashtests/crashtests.list6
-rw-r--r--gfx/tests/gtest/TestConfigManager.cpp6
-rw-r--r--gfx/tests/reftest/reftest.list8
-rw-r--r--gfx/thebes/CoreTextFontList.cpp124
-rw-r--r--gfx/thebes/CoreTextFontList.h26
-rw-r--r--gfx/thebes/DeviceManagerDx.cpp123
-rw-r--r--gfx/thebes/DeviceManagerDx.h10
-rw-r--r--gfx/thebes/IOSPlatformFontList.h36
-rw-r--r--gfx/thebes/IOSPlatformFontList.mm24
-rw-r--r--gfx/thebes/gencjkcisvs.py2
-rw-r--r--gfx/thebes/gfxCoreTextShaper.h2
-rw-r--r--gfx/thebes/gfxDWriteFontList.cpp11
-rw-r--r--gfx/thebes/gfxDWriteFontList.h3
-rw-r--r--gfx/thebes/gfxFT2FontList.cpp49
-rw-r--r--gfx/thebes/gfxFT2FontList.h3
-rw-r--r--gfx/thebes/gfxFcPlatformFontList.cpp43
-rw-r--r--gfx/thebes/gfxFcPlatformFontList.h3
-rw-r--r--gfx/thebes/gfxFontUtils.cpp4
-rw-r--r--gfx/thebes/gfxGDIFontList.cpp7
-rw-r--r--gfx/thebes/gfxGDIFontList.h3
-rw-r--r--gfx/thebes/gfxMacFont.h2
-rw-r--r--gfx/thebes/gfxMacPlatformFontList.h11
-rw-r--r--gfx/thebes/gfxMacPlatformFontList.mm169
-rw-r--r--gfx/thebes/gfxPlatform.cpp77
-rw-r--r--gfx/thebes/gfxPlatformFontList.cpp44
-rw-r--r--gfx/thebes/gfxPlatformFontList.h15
-rw-r--r--gfx/thebes/gfxPlatformMac.cpp39
-rw-r--r--gfx/thebes/gfxQuartzSurface.h6
-rw-r--r--gfx/thebes/gfxUserFontSet.cpp73
-rw-r--r--gfx/thebes/gfxWindowsPlatform.cpp60
-rw-r--r--gfx/thebes/moz.build17
-rw-r--r--gfx/vr/ipc/VRProcessManager.cpp8
-rw-r--r--gfx/webrender_bindings/Cargo.toml2
-rw-r--r--gfx/webrender_bindings/DCLayerTree.cpp255
-rw-r--r--gfx/webrender_bindings/DCLayerTree.h7
-rw-r--r--gfx/webrender_bindings/RenderCompositor.cpp6
-rw-r--r--gfx/webrender_bindings/RenderCompositorNative.cpp8
-rw-r--r--gfx/webrender_bindings/RenderMacIOSurfaceTextureHost.cpp20
-rw-r--r--gfx/webrender_bindings/RenderThread.cpp54
-rw-r--r--gfx/webrender_bindings/RenderThread.h12
-rw-r--r--gfx/webrender_bindings/moz.build2
-rw-r--r--gfx/webrender_bindings/src/bindings.rs8
-rw-r--r--gfx/webrender_bindings/src/lib.rs6
-rw-r--r--gfx/webrender_bindings/src/moz2d_renderer.rs14
-rw-r--r--gfx/wgpu_bindings/Cargo.toml15
-rw-r--r--gfx/wgpu_bindings/moz.yaml4
-rw-r--r--gfx/wgpu_bindings/src/client.rs58
-rw-r--r--gfx/wgpu_bindings/src/command.rs1062
-rw-r--r--gfx/wgpu_bindings/src/lib.rs1
-rw-r--r--gfx/wgpu_bindings/src/server.rs47
-rw-r--r--gfx/wr/Cargo.lock19
-rw-r--r--gfx/wr/peek-poke/peek-poke-derive/src/lib.rs21
-rw-r--r--gfx/wr/webrender/Cargo.toml6
-rw-r--r--gfx/wr/webrender/res/brush.glsl2
-rw-r--r--gfx/wr/webrender/res/brush_linear_gradient.glsl4
-rw-r--r--gfx/wr/webrender/res/cs_border_segment.glsl8
-rw-r--r--gfx/wr/webrender/res/cs_clip_image.glsl117
-rw-r--r--gfx/wr/webrender/res/cs_linear_gradient.glsl4
-rw-r--r--gfx/wr/webrender/res/cs_radial_gradient.glsl4
-rw-r--r--gfx/wr/webrender/res/gpu_buffer.glsl36
-rw-r--r--gfx/wr/webrender/res/gradient.glsl2
-rw-r--r--gfx/wr/webrender/res/prim_shared.glsl6
-rw-r--r--gfx/wr/webrender/res/ps_quad.glsl81
-rw-r--r--gfx/wr/webrender/res/ps_quad_mask.glsl6
-rw-r--r--gfx/wr/webrender/res/ps_quad_textured.glsl2
-rw-r--r--gfx/wr/webrender/res/ps_text_run.glsl2
-rw-r--r--gfx/wr/webrender/res/render_task.glsl25
-rw-r--r--gfx/wr/webrender/src/batch.rs215
-rw-r--r--gfx/wr/webrender/src/device/gl.rs10
-rw-r--r--gfx/wr/webrender/src/frame_builder.rs44
-rw-r--r--gfx/wr/webrender/src/gpu_types.rs56
-rw-r--r--gfx/wr/webrender/src/picture.rs57
-rw-r--r--gfx/wr/webrender/src/prepare.rs313
-rw-r--r--gfx/wr/webrender/src/prim_store/gradient/conic.rs2
-rw-r--r--gfx/wr/webrender/src/prim_store/gradient/linear.rs4
-rw-r--r--gfx/wr/webrender/src/prim_store/gradient/mod.rs4
-rw-r--r--gfx/wr/webrender/src/prim_store/gradient/radial.rs2
-rw-r--r--gfx/wr/webrender/src/prim_store/image.rs2
-rw-r--r--gfx/wr/webrender/src/prim_store/mod.rs31
-rw-r--r--gfx/wr/webrender/src/render_target.rs27
-rw-r--r--gfx/wr/webrender/src/render_task.rs27
-rw-r--r--gfx/wr/webrender/src/render_task_cache.rs6
-rw-r--r--gfx/wr/webrender/src/render_task_graph.rs7
-rw-r--r--gfx/wr/webrender/src/renderer/gpu_buffer.rs173
-rw-r--r--gfx/wr/webrender/src/renderer/mod.rs121
-rw-r--r--gfx/wr/webrender/src/renderer/shade.rs20
-rw-r--r--gfx/wr/webrender/src/renderer/upload.rs12
-rw-r--r--gfx/wr/webrender/src/renderer/vertex.rs67
-rw-r--r--gfx/wr/webrender/src/resource_cache.rs10
-rw-r--r--gfx/wr/webrender/src/spatial_node.rs2
-rw-r--r--gfx/wr/webrender/src/spatial_tree.rs43
-rw-r--r--gfx/wr/webrender/src/telemetry.rs8
-rw-r--r--gfx/wr/webrender_api/src/font.rs22
-rw-r--r--gfx/wr/webrender_build/src/shader_features.rs1
-rw-r--r--gfx/wr/wr_glyph_rasterizer/Cargo.toml6
-rw-r--r--gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs10
-rw-r--r--gfx/wr/wr_glyph_rasterizer/src/lib.rs10
237 files changed, 4826 insertions, 2080 deletions
diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h
index 024723868b..e6b94f86ea 100644
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -1987,7 +1987,7 @@ class DrawTarget : public external::AtomicRefCounted<DrawTarget> {
SurfaceFormat mFormat;
};
-class DrawEventRecorder : public RefCounted<DrawEventRecorder> {
+class DrawEventRecorder : public external::AtomicRefCounted<DrawEventRecorder> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorder)
virtual RecorderType GetRecorderType() const { return RecorderType::UNKNOWN; }
@@ -2160,6 +2160,9 @@ class GFX2D_API Factory {
SurfaceFormat aFormat, SourceSurfaceDeallocator aDeallocator = nullptr,
void* aClosure = nullptr);
+ static already_AddRefed<DataSourceSurface> CopyDataSourceSurface(
+ DataSourceSurface* aSource);
+
static void CopyDataSourceSurface(DataSourceSurface* aSource,
DataSourceSurface* aDest);
diff --git a/gfx/2d/DrawEventRecorder.cpp b/gfx/2d/DrawEventRecorder.cpp
index 967c02f8a0..51f8b836ec 100644
--- a/gfx/2d/DrawEventRecorder.cpp
+++ b/gfx/2d/DrawEventRecorder.cpp
@@ -16,9 +16,7 @@ namespace gfx {
DrawEventRecorderPrivate::DrawEventRecorderPrivate() : mExternalFonts(false) {}
-DrawEventRecorderPrivate::~DrawEventRecorderPrivate() {
- NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
-}
+DrawEventRecorderPrivate::~DrawEventRecorderPrivate() = default;
void DrawEventRecorderPrivate::SetDrawTarget(ReferencePtr aDT) {
NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
diff --git a/gfx/2d/DrawEventRecorder.h b/gfx/2d/DrawEventRecorder.h
index 13380b014a..d62f098784 100644
--- a/gfx/2d/DrawEventRecorder.h
+++ b/gfx/2d/DrawEventRecorder.h
@@ -41,7 +41,7 @@ class DrawEventRecorderPrivate : public DrawEventRecorder {
return true;
}
virtual void FlushItem(IntRect) {}
- void DetachResources() {
+ virtual void DetachResources() {
NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
nsTHashSet<ScaledFont*> fonts = std::move(mStoredFonts);
@@ -116,7 +116,7 @@ class DrawEventRecorderPrivate : public DrawEventRecorder {
return mStoredObjects.EnsureInserted(aObject);
}
- void AddPendingDeletion(std::function<void()>&& aPendingDeletion) {
+ virtual void AddPendingDeletion(std::function<void()>&& aPendingDeletion) {
auto lockedPendingDeletions = mPendingDeletions.Lock();
lockedPendingDeletions->emplace_back(std::move(aPendingDeletion));
}
diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp
index 098ff81117..508dac3f62 100644
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -1398,7 +1398,7 @@ void DrawTargetSkia::Mask(const Pattern& aSource, const Pattern& aMask,
SkPaint maskPaint;
SetPaintPattern(maskPaint, aMask, lock);
- sk_sp<SkShader> maskShader(maskPaint.getShader());
+ sk_sp<SkShader> maskShader(maskPaint.refShader());
if (!maskShader && maskPaint.getAlpha() != 0xFF) {
if (maskPaint.getAlpha() == 0) {
return;
diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp
index abf7a8669b..1bdf597142 100644
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -1106,6 +1106,40 @@ already_AddRefed<DataSourceSurface> Factory::CreateDataSourceSurfaceWithStride(
return nullptr;
}
+already_AddRefed<DataSourceSurface> Factory::CopyDataSourceSurface(
+ DataSourceSurface* aSource) {
+ // Don't worry too much about speed.
+ MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
+ aSource->GetFormat() == SurfaceFormat::R8G8B8X8 ||
+ aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
+ aSource->GetFormat() == SurfaceFormat::B8G8R8X8);
+
+ DataSourceSurface::ScopedMap srcMap(aSource, DataSourceSurface::READ);
+ if (NS_WARN_IF(!srcMap.IsMapped())) {
+ MOZ_ASSERT_UNREACHABLE("CopyDataSourceSurface: Failed to map surface.");
+ return nullptr;
+ }
+
+ IntSize size = aSource->GetSize();
+ SurfaceFormat format = aSource->GetFormat();
+
+ RefPtr<DataSourceSurface> dst = CreateDataSourceSurfaceWithStride(
+ size, format, srcMap.GetStride(), /* aZero */ false);
+ if (NS_WARN_IF(!dst)) {
+ return nullptr;
+ }
+
+ DataSourceSurface::ScopedMap dstMap(dst, DataSourceSurface::WRITE);
+ if (NS_WARN_IF(!dstMap.IsMapped())) {
+ MOZ_ASSERT_UNREACHABLE("CopyDataSourceSurface: Failed to map surface.");
+ return nullptr;
+ }
+
+ SwizzleData(srcMap.GetData(), srcMap.GetStride(), format, dstMap.GetData(),
+ dstMap.GetStride(), format, size);
+ return dst.forget();
+}
+
void Factory::CopyDataSourceSurface(DataSourceSurface* aSource,
DataSourceSurface* aDest) {
// Don't worry too much about speed.
diff --git a/gfx/2d/MacIOSurface.cpp b/gfx/2d/MacIOSurface.cpp
index 8c1c24bc10..1701731d61 100644
--- a/gfx/2d/MacIOSurface.cpp
+++ b/gfx/2d/MacIOSurface.cpp
@@ -5,11 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MacIOSurface.h"
-#include <OpenGL/gl.h>
-#include <OpenGL/CGLIOSurface.h>
+#ifdef XP_MACOSX
+# include <OpenGL/gl.h>
+# include <OpenGL/CGLIOSurface.h>
+#endif
#include <QuartzCore/QuartzCore.h>
#include "GLConsts.h"
-#include "GLContextCGL.h"
+#ifdef XP_MACOSX
+# include "GLContextCGL.h"
+#else
+# include "GLContextEAGL.h"
+#endif
#include "gfxMacUtils.h"
#include "nsPrintfCString.h"
#include "mozilla/Assertions.h"
@@ -223,6 +229,7 @@ already_AddRefed<MacIOSurface> MacIOSurface::CreateNV12OrP010Surface(
surfaceRef.get(), CFSTR("IOSurfaceTransferFunction"),
gfxMacUtils::CFStringForTransferFunction(aTransferFunction));
+#ifdef XP_MACOSX
// Override the color space to be the same as the main display, so that
// CoreAnimation won't try to do any color correction (from the IOSurface
// space, to the display). In the future we may want to try specifying this
@@ -234,6 +241,7 @@ already_AddRefed<MacIOSurface> MacIOSurface::CreateNV12OrP010Surface(
CGColorSpaceCopyICCData(colorSpace.get()));
IOSurfaceSetValue(surfaceRef.get(), CFSTR("IOSurfaceColorSpace"),
colorData.get());
+#endif
RefPtr<MacIOSurface> ioSurface =
new MacIOSurface(std::move(surfaceRef), false, aColorSpace);
@@ -285,6 +293,8 @@ already_AddRefed<MacIOSurface> MacIOSurface::CreateYUV422Surface(
IOSurfaceSetValue(surfaceRef.get(), CFSTR("IOSurfaceYCbCrMatrix"),
CFSTR("ITU_R_709_2"));
}
+
+#ifdef XP_MACOSX
// Override the color space to be the same as the main display, so that
// CoreAnimation won't try to do any color correction (from the IOSurface
// space, to the display). In the future we may want to try specifying this
@@ -296,6 +306,7 @@ already_AddRefed<MacIOSurface> MacIOSurface::CreateYUV422Surface(
CGColorSpaceCopyICCData(colorSpace.get()));
IOSurfaceSetValue(surfaceRef.get(), CFSTR("IOSurfaceColorSpace"),
colorData.get());
+#endif
RefPtr<MacIOSurface> ioSurface =
new MacIOSurface(std::move(surfaceRef), false, aColorSpace);
@@ -482,19 +493,10 @@ ColorDepth MacIOSurface::GetColorDepth() const {
}
}
-CGLError MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx, GLenum target,
- GLenum internalFormat,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- GLuint plane) const {
- return ::CGLTexImageIOSurface2D(ctx, target, internalFormat, width, height,
- format, type, mIOSurfaceRef.get(), plane);
-}
-
-CGLError MacIOSurface::CGLTexImageIOSurface2D(
- mozilla::gl::GLContext* aGL, CGLContextObj ctx, size_t plane,
- mozilla::gfx::SurfaceFormat* aOutReadFormat) {
- MOZ_ASSERT(plane >= 0);
+bool MacIOSurface::BindTexImage(mozilla::gl::GLContext* aGL, size_t aPlane,
+ mozilla::gfx::SurfaceFormat* aOutReadFormat) {
+#ifdef XP_MACOSX
+ MOZ_ASSERT(aPlane >= 0);
bool isCompatibilityProfile = aGL->IsCompatibilityProfile();
OSType pixelFormat = GetPixelFormat();
@@ -504,12 +506,12 @@ CGLError MacIOSurface::CGLTexImageIOSurface2D(
if (pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
MOZ_ASSERT(GetPlaneCount() == 2);
- MOZ_ASSERT(plane < 2);
+ MOZ_ASSERT(aPlane < 2);
// The LOCAL_GL_LUMINANCE and LOCAL_GL_LUMINANCE_ALPHA are the deprecated
// format. So, use LOCAL_GL_RED and LOCAL_GL_RB if we use core profile.
// https://www.khronos.org/opengl/wiki/Image_Format#Legacy_Image_Formats
- if (plane == 0) {
+ if (aPlane == 0) {
internalFormat = format =
(isCompatibilityProfile) ? (LOCAL_GL_LUMINANCE) : (LOCAL_GL_RED);
} else {
@@ -523,12 +525,12 @@ CGLError MacIOSurface::CGLTexImageIOSurface2D(
} else if (pixelFormat == kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange ||
pixelFormat == kCVPixelFormatType_420YpCbCr10BiPlanarFullRange) {
MOZ_ASSERT(GetPlaneCount() == 2);
- MOZ_ASSERT(plane < 2);
+ MOZ_ASSERT(aPlane < 2);
// The LOCAL_GL_LUMINANCE and LOCAL_GL_LUMINANCE_ALPHA are the deprecated
// format. So, use LOCAL_GL_RED and LOCAL_GL_RB if we use core profile.
// https://www.khronos.org/opengl/wiki/Image_Format#Legacy_Image_Formats
- if (plane == 0) {
+ if (aPlane == 0) {
internalFormat = format =
(isCompatibilityProfile) ? (LOCAL_GL_LUMINANCE) : (LOCAL_GL_RED);
} else {
@@ -541,7 +543,7 @@ CGLError MacIOSurface::CGLTexImageIOSurface2D(
}
} else if (pixelFormat == kCVPixelFormatType_422YpCbCr8_yuvs ||
pixelFormat == kCVPixelFormatType_422YpCbCr8FullRange) {
- MOZ_ASSERT(plane == 0);
+ MOZ_ASSERT(aPlane == 0);
// The YCBCR_422_APPLE ext is only available in compatibility profile. So,
// we should use RGB_422_APPLE for core profile. The difference between
// YCBCR_422_APPLE and RGB_422_APPLE is that the YCBCR_422_APPLE converts
@@ -565,7 +567,7 @@ CGLError MacIOSurface::CGLTexImageIOSurface2D(
internalFormat = LOCAL_GL_RGB;
type = LOCAL_GL_UNSIGNED_SHORT_8_8_REV_APPLE;
} else {
- MOZ_ASSERT(plane == 0);
+ MOZ_ASSERT(aPlane == 0);
internalFormat = HasAlpha() ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
format = LOCAL_GL_BGRA;
@@ -576,10 +578,13 @@ CGLError MacIOSurface::CGLTexImageIOSurface2D(
}
}
- auto err =
- CGLTexImageIOSurface2D(ctx, LOCAL_GL_TEXTURE_RECTANGLE_ARB,
- internalFormat, GetDevicePixelWidth(plane),
- GetDevicePixelHeight(plane), format, type, plane);
+ size_t width = GetDevicePixelWidth(aPlane);
+ size_t height = GetDevicePixelHeight(aPlane);
+
+ auto err = ::CGLTexImageIOSurface2D(
+ gl::GLContextCGL::Cast(aGL)->GetCGLContext(),
+ LOCAL_GL_TEXTURE_RECTANGLE_ARB, internalFormat, width, height, format,
+ type, mIOSurfaceRef.get(), aPlane);
if (err) {
const auto formatChars = (const char*)&pixelFormat;
const char formatStr[] = {formatChars[3], formatChars[2], formatChars[1],
@@ -587,13 +592,15 @@ CGLError MacIOSurface::CGLTexImageIOSurface2D(
const nsPrintfCString errStr(
"CGLTexImageIOSurface2D(context, target, 0x%04x,"
" %u, %u, 0x%04x, 0x%04x, iosurfPtr, %u) -> %i",
- internalFormat, uint32_t(GetDevicePixelWidth(plane)),
- uint32_t(GetDevicePixelHeight(plane)), format, type,
- (unsigned int)plane, err);
+ internalFormat, uint32_t(width), uint32_t(height), format, type,
+ (unsigned int)aPlane, err);
gfxCriticalError() << errStr.get() << " (iosurf format: " << formatStr
<< ")";
}
- return err;
+ return !err;
+#else
+ MOZ_CRASH("unimplemented");
+#endif
}
void MacIOSurface::SetColorSpace(const mozilla::gfx::ColorSpace2 cs) const {
diff --git a/gfx/2d/MacIOSurface.h b/gfx/2d/MacIOSurface.h
index ef176430d1..d0ee3baeef 100644
--- a/gfx/2d/MacIOSurface.h
+++ b/gfx/2d/MacIOSurface.h
@@ -8,7 +8,7 @@
#define MacIOSurface_h__
#ifdef XP_DARWIN
# include <CoreVideo/CoreVideo.h>
-# include <IOSurface/IOSurface.h>
+# include <IOSurface/IOSurfaceRef.h>
# include <QuartzCore/QuartzCore.h>
# include <dlfcn.h>
@@ -21,20 +21,19 @@ class GLContext;
}
} // namespace mozilla
+# ifdef XP_MACOSX
struct _CGLContextObject;
typedef _CGLContextObject* CGLContextObj;
-typedef uint32_t IOSurfaceID;
-
-# ifdef XP_IOS
-typedef kern_return_t IOReturn;
-typedef int CGLError;
# endif
+typedef uint32_t IOSurfaceID;
# ifdef XP_MACOSX
# import <OpenGL/OpenGL.h>
# else
-# import <OpenGLES/ES2/gl.h>
+# include "GLTypes.h"
+typedef realGLboolean GLboolean;
+# include <OpenGLES/ES2/gl.h>
# endif
# include "2D.h"
@@ -123,15 +122,15 @@ class MacIOSurface final
return mozilla::gfx::ColorRange::LIMITED;
}
- // We would like to forward declare NSOpenGLContext, but it is an @interface
- // and this file is also used from c++, so we use a void *.
- CGLError CGLTexImageIOSurface2D(
- mozilla::gl::GLContext* aGL, CGLContextObj ctxt, size_t plane,
- mozilla::gfx::SurfaceFormat* aOutReadFormat = nullptr);
- CGLError CGLTexImageIOSurface2D(CGLContextObj ctxt, GLenum target,
- GLenum internalFormat, GLsizei width,
- GLsizei height, GLenum format, GLenum type,
- GLuint plane) const;
+ // Bind this IOSurface to a texture using the most efficient mechanism
+ // available on the current platform.
+ //
+ // Note that on iOS simulator, due to incomplete support for
+ // texImageIOSurface, this will only use texImage2D to upload, and cannot be
+ // used to read-back the GL texture to an IOSurface.
+ bool BindTexImage(mozilla::gl::GLContext* aGL, size_t aPlane,
+ mozilla::gfx::SurfaceFormat* aOutReadFormat = nullptr);
+
already_AddRefed<SourceSurface> GetAsSurface();
// Creates a DrawTarget that wraps the data in the IOSurface. Rendering to
diff --git a/gfx/2d/ScaledFontMac.cpp b/gfx/2d/ScaledFontMac.cpp
index 9528b3527e..7ac1cfc9c9 100644
--- a/gfx/2d/ScaledFontMac.cpp
+++ b/gfx/2d/ScaledFontMac.cpp
@@ -7,7 +7,9 @@
#include "ScaledFontMac.h"
#include "UnscaledFontMac.h"
#include "mozilla/webrender/WebRenderTypes.h"
-#include "nsCocoaFeatures.h"
+#ifdef MOZ_WIDGET_COCOA
+# include "nsCocoaFeatures.h"
+#endif
#include "PathSkia.h"
#include "skia/include/core/SkPaint.h"
#include "skia/include/core/SkPath.h"
@@ -73,6 +75,7 @@ class AutoRelease final {
CTFontRef CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize,
bool aInstalledFont,
CTFontDescriptorRef aFontDesc) {
+#ifdef MOZ_WIDGET_COCOA
// New implementation (see bug 1856035) for macOS 13+.
if (nsCocoaFeatures::OnVenturaOrLater()) {
// Create CTFont, applying any descriptor that was passed (used by
@@ -96,6 +99,7 @@ CTFontRef CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize,
// No variations to set, just return the default CTFont.
return ctFont.forget();
}
+#endif
// Older implementation used up to macOS 12.
CTFontRef ctFont;
diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build
index c04530c72b..d1408b9dc9 100644
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -69,6 +69,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
"UnscaledFontMac.h",
]
UNIFIED_SOURCES += [
+ "MacIOSurface.cpp",
"NativeFontResourceMac.cpp",
"ScaledFontMac.cpp",
]
@@ -188,11 +189,6 @@ SOURCES += [
"InlineTranslator.cpp",
]
-if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
- SOURCES += [
- "MacIOSurface.cpp",
- ]
-
if CONFIG["TARGET_CPU"] == "aarch64" or CONFIG["BUILD_ARM_NEON"]:
SOURCES += [
"BlurNEON.cpp",
diff --git a/gfx/angle/moz.build b/gfx/angle/moz.build
index ea4be831bd..ee870a088e 100644
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -4,7 +4,10 @@
# 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/.
-DIRS += ["targets/translator"]
+DIRS += [
+ "targets/angle_common",
+ "targets/translator",
+]
# Only build libEGL/libGLESv2 on Windows
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
diff --git a/gfx/angle/targets/angle_gpu_info_util/moz.build b/gfx/angle/targets/angle_gpu_info_util/moz.build
index f2fe1dd3d4..7278d2bfcd 100644
--- a/gfx/angle/targets/angle_gpu_info_util/moz.build
+++ b/gfx/angle/targets/angle_gpu_info_util/moz.build
@@ -170,10 +170,6 @@ USE_LIBS += [
"angle_common",
]
-DIRS += [
- "../angle_common",
-]
-
OS_LIBS += [
"dxgi",
"setupapi",
diff --git a/gfx/angle/targets/angle_image_util/moz.build b/gfx/angle/targets/angle_image_util/moz.build
index 8a17982e17..38871adc6e 100644
--- a/gfx/angle/targets/angle_image_util/moz.build
+++ b/gfx/angle/targets/angle_image_util/moz.build
@@ -150,10 +150,6 @@ USE_LIBS += [
"angle_common",
]
-DIRS += [
- "../angle_common",
-]
-
# LDFLAGS += [
# "--color-diagnostics",
# "/call-graph-profile-sort:no",
diff --git a/gfx/angle/targets/libEGL/moz.build b/gfx/angle/targets/libEGL/moz.build
index 9327db4c23..eb8c049493 100644
--- a/gfx/angle/targets/libEGL/moz.build
+++ b/gfx/angle/targets/libEGL/moz.build
@@ -157,11 +157,6 @@ USE_LIBS += [
"libGLESv2",
]
-DIRS += [
- "../angle_common",
- "../libGLESv2",
-]
-
OS_LIBS += [
"advapi32",
"comdlg32",
diff --git a/gfx/angle/targets/libGLESv2/moz.build b/gfx/angle/targets/libGLESv2/moz.build
index dfcf0df719..18d296d084 100644
--- a/gfx/angle/targets/libGLESv2/moz.build
+++ b/gfx/angle/targets/libGLESv2/moz.build
@@ -366,11 +366,9 @@ USE_LIBS += [
]
DIRS += [
- "../angle_common",
"../angle_gpu_info_util",
"../angle_image_util",
"../compression_utils_portable",
- "../translator",
]
OS_LIBS += [
diff --git a/gfx/angle/targets/preprocessor/moz.build b/gfx/angle/targets/preprocessor/moz.build
index 3fbce2e0c4..c790132062 100644
--- a/gfx/angle/targets/preprocessor/moz.build
+++ b/gfx/angle/targets/preprocessor/moz.build
@@ -156,10 +156,6 @@ USE_LIBS += [
"angle_common",
]
-DIRS += [
- "../angle_common",
-]
-
# LDFLAGS += [
# "--color-diagnostics",
# "/call-graph-profile-sort:no",
diff --git a/gfx/angle/targets/translator/moz.build b/gfx/angle/targets/translator/moz.build
index 38dbb74f79..4b59b82403 100644
--- a/gfx/angle/targets/translator/moz.build
+++ b/gfx/angle/targets/translator/moz.build
@@ -298,7 +298,6 @@ USE_LIBS += [
]
DIRS += [
- "../angle_common",
"../preprocessor",
]
diff --git a/gfx/angle/update-angle.py b/gfx/angle/update-angle.py
index 348a1cf745..99d65f84f6 100755
--- a/gfx/angle/update-angle.py
+++ b/gfx/angle/update-angle.py
@@ -5,7 +5,7 @@
assert __name__ == "__main__"
-"""
+r"""
To update ANGLE in Gecko, use Windows with git-bash, and setup depot_tools, python2, and
python3. Because depot_tools expects `python` to be `python2` (shame!), python2 must come
before python3 in your path.
@@ -502,8 +502,18 @@ def export_target(target_full_name) -> Set[str]:
dep_dirs = set(dep_libs)
dep_dirs.discard("zlib")
+ # Those directories are added by gfx/angle/moz.build.
+ already_added_dirs = [
+ "angle_common",
+ "translator",
+ "libEGL",
+ "libGLESv2",
+ ]
+
append_arr(lines, "USE_LIBS", dep_libs)
- append_arr(lines, "DIRS", ["../" + x for x in dep_dirs])
+ append_arr(
+ lines, "DIRS", ["../" + x for x in dep_dirs if x not in already_added_dirs]
+ )
append_arr(lines, "OS_LIBS", os_libs)
append_arr_commented(lines, "LDFLAGS", ldflags)
diff --git a/gfx/config/gfxVars.h b/gfx/config/gfxVars.h
index d520ec7716..d74255b5db 100644
--- a/gfx/config/gfxVars.h
+++ b/gfx/config/gfxVars.h
@@ -99,7 +99,9 @@ class gfxVarReceiver;
_(WebglOopAsyncPresentForceSync, bool, true) \
_(UseAcceleratedCanvas2D, bool, false) \
_(AllowSoftwareWebRenderOGL, bool, false) \
- _(WebglUseHardware, bool, true)
+ _(WebglUseHardware, bool, true) \
+ _(WebRenderOverlayVpAutoHDR, bool, false) \
+ _(WebRenderOverlayVpSuperResolution, bool, false)
/* Add new entries above this line. */
diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp
index dd9fa00235..c5c8995dab 100644
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -1176,8 +1176,6 @@ bool GLBlitHelper::BlitImage(MacIOSurface* const iosurf,
MOZ_ASSERT(false);
return false;
}
- const auto glCGL = static_cast<GLContextCGL*>(mGL);
- const auto cglContext = glCGL->GetCGLContext();
const auto& srcOrigin = OriginPos::BottomLeft;
@@ -1268,8 +1266,7 @@ bool GLBlitHelper::BlitImage(MacIOSurface* const iosurf,
mGL->fBindTexture(texTarget, texs[p]);
mGL->TexParams_SetClampNoMips(texTarget);
- auto err = iosurf->CGLTexImageIOSurface2D(mGL, cglContext, p);
- if (err) {
+ if (!iosurf->BindTexImage(mGL, p)) {
return false;
}
diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp
index 9036653af8..5eba6c58aa 100644
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2049,17 +2049,24 @@ static void ReportArrayContents(
nsTArray<GLContext::NamedResource> copy(aArray.Clone());
copy.Sort();
+ // Accumulate the output in a buffer to avoid interleaved output.
+ nsCString line;
+
GLContext* lastContext = nullptr;
for (uint32_t i = 0; i < copy.Length(); ++i) {
if (lastContext != copy[i].origin) {
- if (lastContext) printf_stderr("\n");
- printf_stderr(" [%p - %s] ", copy[i].origin,
- copy[i].originDeleted ? "deleted" : "live");
+ if (lastContext) {
+ printf_stderr("%s\n", line.BeginReading());
+ line.Assign("");
+ }
+ line.Append(nsPrintfCString(" [%p - %s] ", copy[i].origin,
+ copy[i].originDeleted ? "deleted" : "live"));
lastContext = copy[i].origin;
}
- printf_stderr("%d ", copy[i].name);
+ line.AppendInt(copy[i].name);
+ line.Append(' ');
}
- printf_stderr("\n");
+ printf_stderr("%s\n", line.BeginReading());
}
void GLContext::ReportOutstandingNames() {
diff --git a/gfx/gl/GLContextEAGL.h b/gfx/gl/GLContextEAGL.h
index 6e137e7b70..2b062d1a0f 100644
--- a/gfx/gl/GLContextEAGL.h
+++ b/gfx/gl/GLContextEAGL.h
@@ -10,7 +10,11 @@
#include "GLContext.h"
#include <CoreGraphics/CoreGraphics.h>
-#include <OpenGLES/EAGL.h>
+#ifdef __OBJC__
+# include <OpenGLES/EAGL.h>
+#else
+typedef void EAGLContext;
+#endif
namespace mozilla {
namespace gl {
@@ -23,7 +27,7 @@ class GLContextEAGL : public GLContext {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEAGL, override)
GLContextEAGL(const GLContextDesc&, EAGLContext* context,
- GLContext* sharedContext, ContextProfile profile);
+ GLContext* sharedContext);
~GLContextEAGL();
@@ -36,8 +40,6 @@ class GLContextEAGL : public GLContext {
return static_cast<GLContextEAGL*>(gl);
}
- bool AttachToWindow(nsIWidget* aWidget);
-
EAGLContext* GetEAGLContext() const { return mContext; }
virtual bool MakeCurrentImpl() const override;
@@ -54,18 +56,9 @@ class GLContextEAGL : public GLContext {
virtual GLuint GetDefaultFramebuffer() override { return mBackbufferFB; }
- virtual bool RenewSurface(widget::CompositorWidget*) override {
- // FIXME: should use the passed widget instead of the existing one.
- return RecreateRB();
- }
-
private:
GLuint mBackbufferRB = 0;
GLuint mBackbufferFB = 0;
-
- void* mLayer = nullptr;
-
- bool RecreateRB();
};
} // namespace gl
diff --git a/gfx/gl/GLContextProvider.h b/gfx/gl/GLContextProvider.h
index c63f1ada0b..277b76efa8 100644
--- a/gfx/gl/GLContextProvider.h
+++ b/gfx/gl/GLContextProvider.h
@@ -60,10 +60,6 @@ namespace gl {
# define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderLinux
#endif
-#ifndef GL_CONTEXT_PROVIDER_DEFAULT
-# define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
-#endif
-
#if defined(MOZ_WIDGET_UIKIT)
# define GL_CONTEXT_PROVIDER_NAME GLContextProviderEAGL
# include "GLContextProviderImpl.h"
@@ -73,6 +69,10 @@ namespace gl {
# endif
#endif
+#ifndef GL_CONTEXT_PROVIDER_DEFAULT
+# define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
+#endif
+
#ifdef MOZ_GL_PROVIDER
# define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER
# include "GLContextProviderImpl.h"
diff --git a/gfx/gl/GLContextProviderEAGL.mm b/gfx/gl/GLContextProviderEAGL.mm
index 6e27498028..648d6642d4 100644
--- a/gfx/gl/GLContextProviderEAGL.mm
+++ b/gfx/gl/GLContextProviderEAGL.mm
@@ -5,6 +5,7 @@
#include "GLContextProvider.h"
#include "GLContextEAGL.h"
+#include "GLLibraryLoader.h"
#include "nsDebug.h"
#include "nsIWidget.h"
#include "gfxFailure.h"
@@ -38,58 +39,12 @@ GLContextEAGL::~GLContextEAGL() {
MarkDestroyed();
- if (mLayer) {
- mLayer = nil;
- }
-
if (mContext) {
[EAGLContext setCurrentContext:nil];
[mContext release];
}
}
-bool GLContextEAGL::AttachToWindow(nsIWidget* aWidget) {
- // This should only be called once
- MOZ_ASSERT(!mBackbufferFB && !mBackbufferRB);
-
- UIView* view =
- reinterpret_cast<UIView*>(aWidget->GetNativeData(NS_NATIVE_WIDGET));
-
- if (!view) {
- MOZ_CRASH("no view!");
- }
-
- mLayer = [view layer];
-
- fGenFramebuffers(1, &mBackbufferFB);
- return RecreateRB();
-}
-
-bool GLContextEAGL::RecreateRB() {
- MakeCurrent();
-
- CAEAGLLayer* layer = (CAEAGLLayer*)mLayer;
-
- if (mBackbufferRB) {
- // It doesn't seem to be enough to just call renderbufferStorage: below,
- // we apparently have to recreate the RB.
- fDeleteRenderbuffers(1, &mBackbufferRB);
- mBackbufferRB = 0;
- }
-
- fGenRenderbuffers(1, &mBackbufferRB);
- fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mBackbufferRB);
-
- [mContext renderbufferStorage:LOCAL_GL_RENDERBUFFER fromDrawable:layer];
-
- fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackbufferFB);
- fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
- LOCAL_GL_RENDERBUFFER, mBackbufferRB);
-
- return LOCAL_GL_FRAMEBUFFER_COMPLETE ==
- fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
-}
-
bool GLContextEAGL::MakeCurrentImpl() const {
if (mContext) {
GLContext::ResetTLSCurrentContext();
@@ -107,7 +62,7 @@ bool GLContextEAGL::IsCurrentImpl() const {
static PRFuncPtr GLAPIENTRY GetLoadedProcAddress(const char* const name) {
PRLibrary* lib = nullptr;
- const auto& ret = PR_FindFunctionSymbolAndLibrary(name, &leakedLibRef);
+ const auto& ret = PR_FindFunctionSymbolAndLibrary(name, &lib);
if (lib) {
PR_UnloadLibrary(lib);
}
@@ -173,29 +128,17 @@ static RefPtr<GLContext> CreateEAGLContext(const GLContextDesc& desc,
already_AddRefed<GLContext> GLContextProviderEAGL::CreateForCompositorWidget(
CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
bool aForceAccelerated) {
- if (!aCompositorWidget) {
- MOZ_ASSERT(false);
- return nullptr;
+ CreateContextFlags flags = CreateContextFlags::ALLOW_OFFLINE_RENDERER;
+ if (aForceAccelerated) {
+ flags |= CreateContextFlags::FORBID_SOFTWARE;
}
-
- const GLContextDesc desc = {};
- auto glContext = CreateEAGLContext(desc, GetGlobalContextEAGL());
- if (!glContext) {
- return nullptr;
- }
-
- if (!GLContextEAGL::Cast(glContext)->AttachToWindow(
- aCompositorWidget->RealWidget())) {
- return nullptr;
- }
-
- return glContext.forget();
+ nsCString failureUnused;
+ return CreateHeadless({flags}, &failureUnused);
}
already_AddRefed<GLContext> GLContextProviderEAGL::CreateHeadless(
const GLContextCreateDesc& createDesc, nsACString* const out_failureId) {
auto desc = GLContextDesc{createDesc};
- desc.isOffcreen = true;
return CreateEAGLContext(desc, GetGlobalContextEAGL()).forget();
}
@@ -208,7 +151,8 @@ GLContext* GLContextProviderEAGL::GetGlobalContext() {
MOZ_RELEASE_ASSERT(!gGlobalContext,
"GFX: Global GL context already initialized.");
- RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE);
+ nsCString discardFailureId;
+ RefPtr<GLContext> temp = CreateHeadless({}, &discardFailureId);
gGlobalContext = temp;
if (!gGlobalContext) {
diff --git a/gfx/gl/GLTypes.h b/gfx/gl/GLTypes.h
index f5b317b4b7..6caa1cc623 100644
--- a/gfx/gl/GLTypes.h
+++ b/gfx/gl/GLTypes.h
@@ -55,6 +55,13 @@ typedef signed long int GLsizeiptr;
#endif /* #if !defined(__gltypes_h_) && !defined(__gl_h_) */
+#ifdef XP_IOS
+# ifndef GLdouble_defined
+typedef double GLdouble;
+# endif
+typedef double GLclampd;
+#endif
+
#include <stdint.h>
// ARB_sync
diff --git a/gfx/gl/SharedSurface.cpp b/gfx/gl/SharedSurface.cpp
index 2fbfd3f625..0465926521 100644
--- a/gfx/gl/SharedSurface.cpp
+++ b/gfx/gl/SharedSurface.cpp
@@ -89,13 +89,13 @@ UniquePtr<SurfaceFactory> SurfaceFactory::Create(
return SurfaceFactory_D3D11Interop::Create(gl);
}
#endif
- return nullptr;
+ break;
case layers::TextureType::MacIOSurface:
#ifdef XP_MACOSX
return MakeUnique<SurfaceFactory_IOSurface>(gl);
#else
- return nullptr;
+ break;
#endif
case layers::TextureType::DMABUF:
@@ -105,13 +105,13 @@ UniquePtr<SurfaceFactory> SurfaceFactory::Create(
return SurfaceFactory_DMABUF::Create(gl);
}
#endif
- return nullptr;
+ break;
case layers::TextureType::AndroidNativeWindow:
#ifdef MOZ_WIDGET_ANDROID
return MakeUnique<SurfaceFactory_SurfaceTexture>(gl);
#else
- return nullptr;
+ break;
#endif
case layers::TextureType::AndroidHardwareBuffer:
@@ -121,7 +121,7 @@ UniquePtr<SurfaceFactory> SurfaceFactory::Create(
return SurfaceFactory_AndroidHardwareBuffer::Create(gl);
}
#endif
- return nullptr;
+ break;
case layers::TextureType::EGLImage:
#ifdef MOZ_WIDGET_ANDROID
@@ -129,17 +129,15 @@ UniquePtr<SurfaceFactory> SurfaceFactory::Create(
return SurfaceFactory_EGLImage::Create(gl);
}
#endif
- return nullptr;
+ break;
case layers::TextureType::Unknown:
case layers::TextureType::Last:
break;
}
-#ifdef MOZ_X11
// Silence a warning.
Unused << gl;
-#endif
return nullptr;
}
diff --git a/gfx/gl/SharedSurfaceIO.cpp b/gfx/gl/SharedSurfaceIO.cpp
index 1fd0f22d31..459faa64b3 100644
--- a/gfx/gl/SharedSurfaceIO.cpp
+++ b/gfx/gl/SharedSurfaceIO.cpp
@@ -28,7 +28,7 @@ SurfaceFactory_IOSurface::SurfaceFactory_IOSurface(GLContext& gl)
// -
// Surface
-static void BackTextureWithIOSurf(GLContext* const gl, const GLuint tex,
+static bool BackTextureWithIOSurf(GLContext* const gl, const GLuint tex,
MacIOSurface* const ioSurf) {
MOZ_ASSERT(gl->IsCurrent());
@@ -43,10 +43,7 @@ static void BackTextureWithIOSurf(GLContext* const gl, const GLuint tex,
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T,
LOCAL_GL_CLAMP_TO_EDGE);
- CGLContextObj cgl = GLContextCGL::Cast(gl)->GetCGLContext();
- MOZ_ASSERT(cgl);
-
- ioSurf->CGLTexImageIOSurface2D(gl, cgl, 0);
+ return ioSurf->BindTexImage(gl, 0);
}
/*static*/
@@ -65,7 +62,9 @@ UniquePtr<SharedSurface_IOSurface> SharedSurface_IOSurface::Create(
// -
auto tex = MakeUnique<Texture>(*desc.gl);
- BackTextureWithIOSurf(desc.gl, tex->name, ioSurf);
+ if (!BackTextureWithIOSurf(desc.gl, tex->name, ioSurf)) {
+ return nullptr;
+ }
const GLenum target = LOCAL_GL_TEXTURE_RECTANGLE;
auto fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false,
diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build
index f45e85b8f4..965b0add48 100644
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -12,6 +12,7 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
gl_provider = "CGL"
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "uikit":
gl_provider = "EAGL"
+ DEFINES["GLES_SILENCE_DEPRECATION"] = 1
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
gl_provider = "Linux"
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android":
diff --git a/gfx/ipc/CanvasManagerChild.cpp b/gfx/ipc/CanvasManagerChild.cpp
index eca803bc4b..dee232b6b1 100644
--- a/gfx/ipc/CanvasManagerChild.cpp
+++ b/gfx/ipc/CanvasManagerChild.cpp
@@ -10,6 +10,7 @@
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRef.h"
#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/CanvasShutdownManager.h"
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/layers/ActiveResource.h"
@@ -30,7 +31,10 @@ MOZ_THREAD_LOCAL(CanvasManagerChild*) CanvasManagerChild::sLocalManager;
Atomic<uint32_t> CanvasManagerChild::sNextId(1);
-CanvasManagerChild::CanvasManagerChild(uint32_t aId) : mId(aId) {}
+CanvasManagerChild::CanvasManagerChild(ThreadSafeWorkerRef* aWorkerRef,
+ uint32_t aId)
+ : mWorkerRef(aWorkerRef), mId(aId) {}
+
CanvasManagerChild::~CanvasManagerChild() = default;
void CanvasManagerChild::ActorDestroy(ActorDestroyReason aReason) {
@@ -42,11 +46,6 @@ void CanvasManagerChild::ActorDestroy(ActorDestroyReason aReason) {
}
void CanvasManagerChild::DestroyInternal() {
- std::set<CanvasRenderingContext2D*> activeCanvas = std::move(mActiveCanvas);
- for (const auto& i : activeCanvas) {
- i->OnShutdown();
- }
-
if (mActiveResourceTracker) {
mActiveResourceTracker->AgeAllGenerations();
mActiveResourceTracker.reset();
@@ -56,6 +55,10 @@ void CanvasManagerChild::DestroyInternal() {
mCanvasChild->Destroy();
mCanvasChild = nullptr;
}
+
+ if (auto* shutdownManager = CanvasShutdownManager::Get()) {
+ shutdownManager->OnRemoteCanvasLost();
+ }
}
void CanvasManagerChild::Destroy() {
@@ -67,12 +70,6 @@ void CanvasManagerChild::Destroy() {
}
/* static */ void CanvasManagerChild::Shutdown() {
- MOZ_ASSERT(NS_IsMainThread());
-
- // The worker threads should destroy their own CanvasManagerChild instances
- // during their shutdown sequence. We just need to take care of the main
- // thread. We need to init here because we may have never created a
- // CanvasManagerChild for the main thread in the first place.
if (sLocalManager.init()) {
RefPtr<CanvasManagerChild> manager = sLocalManager.get();
if (manager) {
@@ -103,6 +100,11 @@ void CanvasManagerChild::Destroy() {
return managerWeak;
}
+ auto* shutdownManager = CanvasShutdownManager::Get();
+ if (NS_WARN_IF(!shutdownManager)) {
+ return nullptr;
+ }
+
// We are only used on the main thread, or on worker threads.
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT_IF(!worker, NS_IsMainThread());
@@ -121,29 +123,8 @@ void CanvasManagerChild::Destroy() {
return nullptr;
}
- auto manager = MakeRefPtr<CanvasManagerChild>(sNextId++);
-
- if (worker) {
- // The ThreadSafeWorkerRef will let us know when the worker is shutting
- // down. This will let us clear our threadlocal reference and close the
- // actor. We rely upon an explicit shutdown for the main thread.
- RefPtr<StrongWorkerRef> workerRef = StrongWorkerRef::Create(
- worker, "CanvasManager", [manager]() { manager->Destroy(); });
- if (NS_WARN_IF(!workerRef)) {
- return nullptr;
- }
-
- manager->mWorkerRef = new ThreadSafeWorkerRef(workerRef);
- } else if (NS_IsMainThread()) {
- if (NS_WARN_IF(
- AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed))) {
- return nullptr;
- }
- } else {
- MOZ_ASSERT_UNREACHABLE("Can only be used on main or DOM worker threads!");
- return nullptr;
- }
-
+ auto manager = MakeRefPtr<CanvasManagerChild>(shutdownManager->GetWorkerRef(),
+ sNextId++);
if (NS_WARN_IF(!childEndpoint.Bind(manager))) {
return nullptr;
}
@@ -163,6 +144,7 @@ void CanvasManagerChild::Destroy() {
}
manager->SendInitialize(manager->Id());
+ shutdownManager->OnRemoteCanvasRestored();
sLocalManager.set(manager);
return manager;
}
@@ -175,16 +157,6 @@ void CanvasManagerChild::Destroy() {
return sLocalManager.get();
}
-void CanvasManagerChild::AddShutdownObserver(
- dom::CanvasRenderingContext2D* aCanvas) {
- mActiveCanvas.insert(aCanvas);
-}
-
-void CanvasManagerChild::RemoveShutdownObserver(
- dom::CanvasRenderingContext2D* aCanvas) {
- mActiveCanvas.erase(aCanvas);
-}
-
void CanvasManagerChild::EndCanvasTransaction() {
if (!mCanvasChild) {
return;
@@ -224,8 +196,9 @@ RefPtr<layers::CanvasChild> CanvasManagerChild::GetCanvasChild() {
}
if (!mCanvasChild) {
- mCanvasChild = MakeAndAddRef<layers::CanvasChild>();
+ mCanvasChild = MakeAndAddRef<layers::CanvasChild>(mWorkerRef);
if (!SendPCanvasConstructor(mCanvasChild)) {
+ mCanvasChild->Destroy();
mCanvasChild = nullptr;
}
}
diff --git a/gfx/ipc/CanvasManagerChild.h b/gfx/ipc/CanvasManagerChild.h
index 6369d87ada..c59ba7c502 100644
--- a/gfx/ipc/CanvasManagerChild.h
+++ b/gfx/ipc/CanvasManagerChild.h
@@ -10,7 +10,6 @@
#include "mozilla/gfx/PCanvasManagerChild.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/ThreadLocal.h"
-#include <set>
namespace mozilla {
namespace dom {
@@ -35,7 +34,8 @@ class CanvasManagerChild final : public PCanvasManagerChild {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CanvasManagerChild, override);
- explicit CanvasManagerChild(uint32_t aId);
+ explicit CanvasManagerChild(dom::ThreadSafeWorkerRef* aWorkerRef,
+ uint32_t aId);
uint32_t Id() const { return mId; }
already_AddRefed<DataSourceSurface> GetSnapshot(
uint32_t aManagerId, int32_t aProtocolId,
@@ -49,9 +49,6 @@ class CanvasManagerChild final : public PCanvasManagerChild {
static bool CreateParent(
mozilla::ipc::Endpoint<PCanvasManagerParent>&& aEndpoint);
- void AddShutdownObserver(dom::CanvasRenderingContext2D* aCanvas);
- void RemoveShutdownObserver(dom::CanvasRenderingContext2D* aCanvas);
-
bool IsCanvasActive() { return mActive; }
void EndCanvasTransaction();
void ClearCachedResources();
@@ -73,7 +70,6 @@ class CanvasManagerChild final : public PCanvasManagerChild {
RefPtr<layers::CanvasChild> mCanvasChild;
RefPtr<webgpu::WebGPUChild> mWebGPUChild;
UniquePtr<layers::ActiveResourceTracker> mActiveResourceTracker;
- std::set<dom::CanvasRenderingContext2D*> mActiveCanvas;
const uint32_t mId;
bool mActive = true;
bool mBlocked = false;
diff --git a/gfx/ipc/CanvasShutdownManager.cpp b/gfx/ipc/CanvasShutdownManager.cpp
new file mode 100644
index 0000000000..d7fc96d255
--- /dev/null
+++ b/gfx/ipc/CanvasShutdownManager.cpp
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "CanvasShutdownManager.h"
+#include "mozilla/AppShutdown.h"
+#include "mozilla/dom/CanvasRenderingContext2D.h"
+#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/WorkerRef.h"
+#include "mozilla/dom/WorkerRunnable.h"
+#include "mozilla/gfx/CanvasManagerChild.h"
+
+using namespace mozilla::dom;
+
+namespace mozilla::gfx {
+
+StaticMutex CanvasShutdownManager::sManagersMutex;
+std::set<CanvasShutdownManager*> CanvasShutdownManager::sManagers;
+
+// The owning thread will tell us to close when it is shutdown, either via
+// CanvasShutdownManager::Shutdown for the main thread, or via a shutdown
+// callback from ThreadSafeWorkerRef for worker threads.
+MOZ_THREAD_LOCAL(CanvasShutdownManager*) CanvasShutdownManager::sLocalManager;
+
+CanvasShutdownManager::CanvasShutdownManager(StrongWorkerRef* aWorkerRef)
+ : mWorkerRef(new ThreadSafeWorkerRef(aWorkerRef)) {}
+
+CanvasShutdownManager::CanvasShutdownManager() = default;
+CanvasShutdownManager::~CanvasShutdownManager() = default;
+
+void CanvasShutdownManager::Destroy() {
+ std::set<CanvasRenderingContext2D*> activeCanvas = std::move(mActiveCanvas);
+ for (const auto& i : activeCanvas) {
+ i->OnShutdown();
+ }
+
+ CanvasManagerChild::Shutdown();
+ mWorkerRef = nullptr;
+}
+
+/* static */ void CanvasShutdownManager::Shutdown() {
+ auto* manager = MaybeGet();
+ if (!manager) {
+ return;
+ }
+
+ {
+ StaticMutexAutoLock lock(sManagersMutex);
+ sManagers.erase(manager);
+ }
+
+ sLocalManager.set(nullptr);
+ manager->Destroy();
+ delete manager;
+}
+
+/* static */ CanvasShutdownManager* CanvasShutdownManager::MaybeGet() {
+ if (NS_WARN_IF(!sLocalManager.init())) {
+ return nullptr;
+ }
+
+ return sLocalManager.get();
+}
+
+/* static */ CanvasShutdownManager* CanvasShutdownManager::Get() {
+ if (NS_WARN_IF(!sLocalManager.init())) {
+ return nullptr;
+ }
+
+ CanvasShutdownManager* managerWeak = sLocalManager.get();
+ if (managerWeak) {
+ return managerWeak;
+ }
+
+ if (WorkerPrivate* worker = GetCurrentThreadWorkerPrivate()) {
+ // The ThreadSafeWorkerRef will let us know when the worker is shutting
+ // down. This will let us clear our threadlocal reference and close the
+ // actor. We rely upon an explicit shutdown for the main thread.
+ RefPtr<StrongWorkerRef> workerRef = StrongWorkerRef::Create(
+ worker, "CanvasShutdownManager", []() { Shutdown(); });
+ if (NS_WARN_IF(!workerRef)) {
+ return nullptr;
+ }
+
+ CanvasShutdownManager* manager = new CanvasShutdownManager(workerRef);
+ sLocalManager.set(manager);
+
+ StaticMutexAutoLock lock(sManagersMutex);
+ sManagers.insert(manager);
+ return manager;
+ }
+
+ if (NS_IsMainThread()) {
+ if (NS_WARN_IF(
+ AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed))) {
+ return nullptr;
+ }
+
+ CanvasShutdownManager* manager = new CanvasShutdownManager();
+ sLocalManager.set(manager);
+
+ StaticMutexAutoLock lock(sManagersMutex);
+ sManagers.insert(manager);
+ return manager;
+ }
+
+ MOZ_ASSERT_UNREACHABLE("Can only be used on main or DOM worker threads!");
+ return nullptr;
+}
+
+void CanvasShutdownManager::AddShutdownObserver(
+ dom::CanvasRenderingContext2D* aCanvas) {
+ mActiveCanvas.insert(aCanvas);
+}
+
+void CanvasShutdownManager::RemoveShutdownObserver(
+ dom::CanvasRenderingContext2D* aCanvas) {
+ mActiveCanvas.erase(aCanvas);
+}
+
+void CanvasShutdownManager::OnRemoteCanvasLost() {
+ // Note that the canvas cannot do anything that mutates our state. It will
+ // dispatch for anything that risks re-entrancy.
+ for (const auto& canvas : mActiveCanvas) {
+ canvas->OnRemoteCanvasLost();
+ }
+}
+
+void CanvasShutdownManager::OnRemoteCanvasRestored() {
+ // Note that the canvas cannot do anything that mutates our state. It will
+ // dispatch for anything that risks re-entrancy.
+ for (const auto& canvas : mActiveCanvas) {
+ canvas->OnRemoteCanvasRestored();
+ }
+}
+
+/* static */ void CanvasShutdownManager::MaybeRestoreRemoteCanvas() {
+ // Calling Get will recreate the CanvasManagerChild, which in turn will
+ // cause us to call OnRemoteCanvasRestore upon success.
+ if (CanvasShutdownManager* manager = MaybeGet()) {
+ if (!manager->mActiveCanvas.empty()) {
+ CanvasManagerChild::Get();
+ }
+ }
+}
+
+/* static */ void CanvasShutdownManager::OnCompositorManagerRestored() {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ class RestoreRunnable final : public WorkerRunnable {
+ public:
+ explicit RestoreRunnable(WorkerPrivate* aWorkerPrivate)
+ : WorkerRunnable(aWorkerPrivate,
+ "CanvasShutdownManager::RestoreRunnable") {}
+
+ bool WorkerRun(JSContext*, WorkerPrivate*) override {
+ MaybeRestoreRemoteCanvas();
+ return true;
+ }
+ };
+
+ // We can restore the main thread canvases immediately.
+ MaybeRestoreRemoteCanvas();
+
+ // And dispatch to restore any DOM worker canvases. This is safe because we
+ // remove the manager from sManagers before clearing mWorkerRef during DOM
+ // worker shutdown.
+ StaticMutexAutoLock lock(sManagersMutex);
+ for (const auto& manager : sManagers) {
+ if (manager->mWorkerRef) {
+ auto task = MakeRefPtr<RestoreRunnable>(manager->mWorkerRef->Private());
+ task->Dispatch();
+ }
+ }
+}
+
+} // namespace mozilla::gfx
diff --git a/gfx/ipc/CanvasShutdownManager.h b/gfx/ipc/CanvasShutdownManager.h
new file mode 100644
index 0000000000..803d6a1eb8
--- /dev/null
+++ b/gfx/ipc/CanvasShutdownManager.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+#ifndef _include_gfx_ipc_CanvasShutdownManager_h__
+#define _include_gfx_ipc_CanvasShutdownManager_h__
+
+#include "mozilla/RefPtr.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/ThreadLocal.h"
+#include <set>
+
+namespace mozilla {
+namespace dom {
+class CanvasRenderingContext2D;
+class StrongWorkerRef;
+class ThreadSafeWorkerRef;
+} // namespace dom
+
+namespace gfx {
+
+class CanvasShutdownManager final {
+ public:
+ static CanvasShutdownManager* Get();
+ static CanvasShutdownManager* MaybeGet();
+ static void Shutdown();
+
+ dom::ThreadSafeWorkerRef* GetWorkerRef() const { return mWorkerRef; }
+ void AddShutdownObserver(dom::CanvasRenderingContext2D* aCanvas);
+ void RemoveShutdownObserver(dom::CanvasRenderingContext2D* aCanvas);
+
+ static void OnCompositorManagerRestored();
+
+ void OnRemoteCanvasLost();
+ void OnRemoteCanvasRestored();
+
+ private:
+ explicit CanvasShutdownManager(dom::StrongWorkerRef* aWorkerRef);
+ CanvasShutdownManager();
+ ~CanvasShutdownManager();
+ void Destroy();
+
+ static void MaybeRestoreRemoteCanvas();
+
+ RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
+ std::set<dom::CanvasRenderingContext2D*> mActiveCanvas;
+ static MOZ_THREAD_LOCAL(CanvasShutdownManager*) sLocalManager;
+
+ static StaticMutex sManagersMutex;
+ static std::set<CanvasShutdownManager*> sManagers;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // _include_gfx_ipc_CanvasShutdownManager_h__
diff --git a/gfx/ipc/GPUParent.cpp b/gfx/ipc/GPUParent.cpp
index 283fb87ee9..f4240a5d97 100644
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -571,6 +571,19 @@ mozilla::ipc::IPCResult GPUParent::RecvPreferenceUpdate(const Pref& aPref) {
return IPC_OK();
}
+mozilla::ipc::IPCResult GPUParent::RecvScreenInformationChanged() {
+#if defined(XP_WIN)
+ DeviceManagerDx::Get()->PostUpdateMonitorInfo();
+#endif
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUParent::RecvNotifyBatteryInfo(
+ const BatteryInformation& aBatteryInfo) {
+ wr::RenderThread::Get()->SetBatteryInfo(aBatteryInfo);
+ return IPC_OK();
+}
+
static void CopyFeatureChange(Feature aFeature, Maybe<FeatureFailure>* aOut) {
FeatureState& feature = gfxConfig::GetFeature(aFeature);
if (feature.DisabledByDefault() || feature.IsEnabled()) {
diff --git a/gfx/ipc/GPUParent.h b/gfx/ipc/GPUParent.h
index 434c9eab79..4c01761e77 100644
--- a/gfx/ipc/GPUParent.h
+++ b/gfx/ipc/GPUParent.h
@@ -74,6 +74,9 @@ class GPUParent final : public PGPUParent {
Endpoint<PProfilerChild>&& aEndpoint);
mozilla::ipc::IPCResult RecvUpdateVar(const GfxVarUpdate& pref);
mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& pref);
+ mozilla::ipc::IPCResult RecvScreenInformationChanged();
+ mozilla::ipc::IPCResult RecvNotifyBatteryInfo(
+ const BatteryInformation& aBatteryInfo);
mozilla::ipc::IPCResult RecvNewContentCompositorManager(
Endpoint<PCompositorManagerParent>&& aEndpoint,
const ContentParentId& aChildId, uint32_t aNamespace);
diff --git a/gfx/ipc/GPUProcessManager.cpp b/gfx/ipc/GPUProcessManager.cpp
index babc523e3a..97f4d47111 100644
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -136,10 +136,28 @@ GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic,
}
} else if (!strcmp(aTopic, "application-background")) {
mManager->mAppInForeground = false;
+ } else if (!strcmp(aTopic, "screen-information-changed")) {
+ mManager->ScreenInformationChanged();
}
return NS_OK;
}
+GPUProcessManager::BatteryObserver::BatteryObserver(GPUProcessManager* aManager)
+ : mManager(aManager) {
+ hal::RegisterBatteryObserver(this);
+}
+
+void GPUProcessManager::BatteryObserver::Notify(
+ const hal::BatteryInformation& aBatteryInfo) {
+ mManager->NotifyBatteryInfo(aBatteryInfo);
+}
+
+void GPUProcessManager::BatteryObserver::ShutDown() {
+ hal::UnregisterBatteryObserver(this);
+}
+
+GPUProcessManager::BatteryObserver::~BatteryObserver() {}
+
void GPUProcessManager::OnXPCOMShutdown() {
if (mObserver) {
nsContentUtils::UnregisterShutdownObserver(mObserver);
@@ -148,6 +166,7 @@ void GPUProcessManager::OnXPCOMShutdown() {
if (obsServ) {
obsServ->RemoveObserver(mObserver, "application-foreground");
obsServ->RemoveObserver(mObserver, "application-background");
+ obsServ->RemoveObserver(mObserver, "screen-information-changed");
}
mObserver = nullptr;
}
@@ -172,6 +191,21 @@ void GPUProcessManager::OnPreferenceChange(const char16_t* aData) {
}
}
+void GPUProcessManager::ScreenInformationChanged() {
+#if defined(XP_WIN)
+ if (!!mGPUChild) {
+ mGPUChild->SendScreenInformationChanged();
+ }
+#endif
+}
+
+void GPUProcessManager::NotifyBatteryInfo(
+ const hal::BatteryInformation& aBatteryInfo) {
+ if (mGPUChild) {
+ mGPUChild->SendNotifyBatteryInfo(aBatteryInfo);
+ }
+}
+
void GPUProcessManager::ResetProcessStable() {
mTotalProcessAttempts++;
mProcessStable = false;
@@ -207,6 +241,7 @@ bool GPUProcessManager::LaunchGPUProcess() {
if (obsServ) {
obsServ->AddObserver(mObserver, "application-foreground", false);
obsServ->AddObserver(mObserver, "application-background", false);
+ obsServ->AddObserver(mObserver, "screen-information-changed", false);
}
}
@@ -566,6 +601,9 @@ void GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost) {
std::move(vsyncChild));
mGPUChild->SendInitVsyncBridge(std::move(vsyncParent));
+ MOZ_ASSERT(!mBatteryObserver);
+ mBatteryObserver = new BatteryObserver(this);
+
// Flush any pref updates that happened during launch and weren't
// included in the blobs set up in LaunchGPUProcess.
for (const mozilla::dom::Pref& pref : mQueuedPrefs) {
@@ -573,12 +611,11 @@ void GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost) {
}
mQueuedPrefs.Clear();
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::GPUProcessStatus, "Running"_ns);
+ CrashReporter::RecordAnnotationCString(
+ CrashReporter::Annotation::GPUProcessStatus, "Running");
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::GPUProcessLaunchCount,
- static_cast<int>(mTotalProcessAttempts));
+ CrashReporter::RecordAnnotationU32(
+ CrashReporter::Annotation::GPUProcessLaunchCount, mTotalProcessAttempts);
ReinitializeRendering();
}
@@ -754,8 +791,9 @@ void GPUProcessManager::NotifyWebRenderError(wr::WebRenderError aError) {
Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(aReason));
}
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::DeviceResetReason, int(aReason));
+ CrashReporter::RecordAnnotationU32(
+ CrashReporter::Annotation::DeviceResetReason,
+ static_cast<uint32_t>(aReason));
}
bool GPUProcessManager::OnDeviceReset(bool aTrackThreshold) {
@@ -1062,9 +1100,13 @@ void GPUProcessManager::DestroyProcess(bool aUnexpectedShutdown) {
mVsyncBridge->Close();
mVsyncBridge = nullptr;
}
+ if (mBatteryObserver) {
+ mBatteryObserver->ShutDown();
+ mBatteryObserver = nullptr;
+ }
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::GPUProcessStatus, "Destroyed"_ns);
+ CrashReporter::RecordAnnotationCString(
+ CrashReporter::Annotation::GPUProcessStatus, "Destroyed");
}
already_AddRefed<CompositorSession> GPUProcessManager::CreateTopLevelCompositor(
diff --git a/gfx/ipc/GPUProcessManager.h b/gfx/ipc/GPUProcessManager.h
index bf5b7e6587..8b58d15b54 100644
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -14,6 +14,7 @@
#include "mozilla/gfx/GPUProcessHost.h"
#include "mozilla/gfx/PGPUChild.h"
#include "mozilla/gfx/Point.h"
+#include "mozilla/Hal.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/TaskFactory.h"
#include "mozilla/layers/LayersTypes.h"
@@ -214,6 +215,7 @@ class GPUProcessManager final : public GPUProcessHost::Listener {
// Called from our xpcom-shutdown observer.
void OnXPCOMShutdown();
void OnPreferenceChange(const char16_t* aData);
+ void ScreenInformationChanged();
bool CreateContentCompositorManager(
base::ProcessId aOtherProcess, dom::ContentParentId aChildId,
@@ -309,6 +311,8 @@ class GPUProcessManager final : public GPUProcessHost::Listener {
DISALLOW_COPY_AND_ASSIGN(GPUProcessManager);
+ void NotifyBatteryInfo(const hal::BatteryInformation& aBatteryInfo);
+
class Observer final : public nsIObserver {
public:
NS_DECL_ISUPPORTS
@@ -322,10 +326,25 @@ class GPUProcessManager final : public GPUProcessHost::Listener {
};
friend class Observer;
+ class BatteryObserver final : public hal::BatteryObserver {
+ public:
+ NS_INLINE_DECL_REFCOUNTING(BatteryObserver)
+ explicit BatteryObserver(GPUProcessManager* aManager);
+
+ void Notify(const hal::BatteryInformation& aBatteryInfo) override;
+ void ShutDown();
+
+ protected:
+ virtual ~BatteryObserver();
+
+ GPUProcessManager* mManager;
+ };
+
private:
bool mDecodeVideoOnGpuProcess = true;
RefPtr<Observer> mObserver;
+ RefPtr<BatteryObserver> mBatteryObserver;
mozilla::ipc::TaskFactory<GPUProcessManager> mTaskFactory;
RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
uint32_t mNextNamespace;
diff --git a/gfx/ipc/PGPU.ipdl b/gfx/ipc/PGPU.ipdl
index b6e84bf142..aabb81dc43 100644
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -41,6 +41,7 @@ using mozilla::layers::OverlayInfo from "mozilla/layers/OverlayInfo.h";
using mozilla::layers::SwapChainInfo from "mozilla/layers/OverlayInfo.h";
using mozilla::media::MediaCodecsSupported from "MediaCodecsSupport.h";
using mozilla::layers::VideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h";
+using mozilla::hal::BatteryInformation from "mozilla/hal_sandbox/PHal.h";
namespace mozilla {
namespace gfx {
@@ -79,6 +80,8 @@ parent:
async UpdateVar(GfxVarUpdate var);
async PreferenceUpdate(Pref pref);
+ async ScreenInformationChanged();
+ async NotifyBatteryInfo(BatteryInformation aBatteryInfo);
// Create a new content-process compositor bridge.
async NewContentCompositorManager(Endpoint<PCompositorManagerParent> endpoint, ContentParentId childId, uint32_t aNamespace);
diff --git a/gfx/ipc/moz.build b/gfx/ipc/moz.build
index b8a52079e4..cc007a8193 100644
--- a/gfx/ipc/moz.build
+++ b/gfx/ipc/moz.build
@@ -13,6 +13,7 @@ EXPORTS.mozilla.gfx += [
"CanvasManagerChild.h",
"CanvasManagerParent.h",
"CanvasRenderThread.h",
+ "CanvasShutdownManager.h",
"CrossProcessPaint.h",
"FileHandleWrapper.h",
"GPUChild.h",
@@ -42,6 +43,7 @@ UNIFIED_SOURCES += [
"CanvasManagerChild.cpp",
"CanvasManagerParent.cpp",
"CanvasRenderThread.cpp",
+ "CanvasShutdownManager.cpp",
"CompositorSession.cpp",
"CompositorWidgetVsyncObserver.cpp",
"CrossProcessPaint.cpp",
diff --git a/gfx/layers/BuildConstants.h b/gfx/layers/BuildConstants.h
index 6db150d136..cebdd35371 100644
--- a/gfx/layers/BuildConstants.h
+++ b/gfx/layers/BuildConstants.h
@@ -52,6 +52,13 @@ constexpr bool kIsAndroid =
false;
#endif
+constexpr bool kIsDmd =
+#ifdef MOZ_DMD
+ true;
+#else
+ false;
+#endif
+
} // namespace mozilla
#endif // BUILD_CONSTANTS_H_
diff --git a/gfx/layers/CanvasDrawEventRecorder.cpp b/gfx/layers/CanvasDrawEventRecorder.cpp
index 1bf928b816..af143bf5cb 100644
--- a/gfx/layers/CanvasDrawEventRecorder.cpp
+++ b/gfx/layers/CanvasDrawEventRecorder.cpp
@@ -8,6 +8,11 @@
#include <string.h>
+#include "mozilla/dom/WorkerCommon.h"
+#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/WorkerRef.h"
+#include "mozilla/dom/WorkerRunnable.h"
+#include "mozilla/layers/TextureRecorded.h"
#include "mozilla/layers/SharedSurfacesChild.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "RecordedCanvasEventImpl.h"
@@ -34,7 +39,9 @@ static Maybe<ShmemAndHandle> CreateAndMapShmem(size_t aSize) {
return Some(ShmemAndHandle{shmem.forget(), std::move(shmemHandle)});
}
-CanvasDrawEventRecorder::CanvasDrawEventRecorder() {
+CanvasDrawEventRecorder::CanvasDrawEventRecorder(
+ dom::ThreadSafeWorkerRef* aWorkerRef)
+ : mWorkerRef(aWorkerRef), mIsOnWorker(!!aWorkerRef) {
mDefaultBufferSize = ipc::SharedMemory::PageAlignedSize(
StaticPrefs::gfx_canvas_remote_default_buffer_size());
mMaxDefaultBuffers = StaticPrefs::gfx_canvas_remote_max_default_buffers();
@@ -43,7 +50,10 @@ CanvasDrawEventRecorder::CanvasDrawEventRecorder() {
mDropBufferOnZero = mDropBufferLimit;
}
+CanvasDrawEventRecorder::~CanvasDrawEventRecorder() { MOZ_ASSERT(!mWorkerRef); }
+
bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
+ TextureType aWebglTextureType,
gfx::BackendType aBackendType,
UniquePtr<Helpers> aHelpers) {
NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder);
@@ -95,7 +105,7 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
return false;
}
- if (!mHelpers->InitTranslator(aTextureType, aBackendType,
+ if (!mHelpers->InitTranslator(aTextureType, aWebglTextureType, aBackendType,
std::move(header->handle),
std::move(bufferHandles), mDefaultBufferSize,
std::move(readerSem), std::move(writerSem))) {
@@ -317,6 +327,106 @@ void CanvasDrawEventRecorder::CheckAndSignalReader() {
} while (true);
}
+void CanvasDrawEventRecorder::DetachResources() {
+ NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder);
+
+ DrawEventRecorderPrivate::DetachResources();
+
+ {
+ auto lockedPendingDeletions = mPendingDeletions.Lock();
+ mWorkerRef = nullptr;
+ }
+}
+
+void CanvasDrawEventRecorder::QueueProcessPendingDeletionsLocked(
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder) {
+ if (!mWorkerRef) {
+ MOZ_RELEASE_ASSERT(
+ !mIsOnWorker,
+ "QueueProcessPendingDeletionsLocked called after worker shutdown!");
+
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "CanvasDrawEventRecorder::QueueProcessPendingDeletionsLocked",
+ [self = std::move(aRecorder)]() { self->ProcessPendingDeletions(); }));
+ return;
+ }
+
+ if (!NS_IsMainThread()) {
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "CanvasDrawEventRecorder::QueueProcessPendingDeletionsLocked",
+ [self = std::move(aRecorder)]() mutable {
+ self->QueueProcessPendingDeletions(std::move(self));
+ }));
+ return;
+ }
+
+ class ProcessPendingRunnable final : public dom::WorkerRunnable {
+ public:
+ ProcessPendingRunnable(dom::WorkerPrivate* aWorkerPrivate,
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder)
+ : dom::WorkerRunnable(aWorkerPrivate),
+ mRecorder(std::move(aRecorder)) {}
+
+ bool WorkerRun(JSContext*, dom::WorkerPrivate*) override {
+ RefPtr<CanvasDrawEventRecorder> recorder = std::move(mRecorder);
+ recorder->ProcessPendingDeletions();
+ return true;
+ }
+
+ private:
+ RefPtr<CanvasDrawEventRecorder> mRecorder;
+ };
+
+ auto task = MakeRefPtr<ProcessPendingRunnable>(mWorkerRef->Private(),
+ std::move(aRecorder));
+ if (NS_WARN_IF(!task->Dispatch())) {
+ MOZ_CRASH("ProcessPendingRunnable leaked!");
+ }
+}
+
+void CanvasDrawEventRecorder::QueueProcessPendingDeletions(
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder) {
+ auto lockedPendingDeletions = mPendingDeletions.Lock();
+ if (lockedPendingDeletions->empty()) {
+ // We raced to handle the deletions, and something got there first.
+ return;
+ }
+
+ QueueProcessPendingDeletionsLocked(std::move(aRecorder));
+}
+
+void CanvasDrawEventRecorder::AddPendingDeletion(
+ std::function<void()>&& aPendingDeletion) {
+ PendingDeletionsVector pendingDeletions;
+
+ {
+ auto lockedPendingDeletions = mPendingDeletions.Lock();
+ bool wasEmpty = lockedPendingDeletions->empty();
+ lockedPendingDeletions->emplace_back(std::move(aPendingDeletion));
+
+ MOZ_RELEASE_ASSERT(!mIsOnWorker || mWorkerRef,
+ "AddPendingDeletion called after worker shutdown!");
+
+ // If we are not on the owning thread, we must queue an event to run the
+ // deletions, if we transitioned from empty to non-empty.
+ if ((mWorkerRef && !mWorkerRef->Private()->IsOnCurrentThread()) ||
+ (!mWorkerRef && !NS_IsMainThread())) {
+ if (wasEmpty) {
+ RefPtr<CanvasDrawEventRecorder> self(this);
+ QueueProcessPendingDeletionsLocked(std::move(self));
+ }
+ return;
+ }
+
+ // Otherwise, we can just run all of them right now.
+ pendingDeletions.swap(*lockedPendingDeletions);
+ }
+
+ for (const auto& pendingDeletion : pendingDeletions) {
+ pendingDeletion();
+ }
+}
+
void CanvasDrawEventRecorder::StoreSourceSurfaceRecording(
gfx::SourceSurface* aSurface, const char* aReason) {
NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder);
diff --git a/gfx/layers/CanvasDrawEventRecorder.h b/gfx/layers/CanvasDrawEventRecorder.h
index a4b1261cfb..c9eacf27ac 100644
--- a/gfx/layers/CanvasDrawEventRecorder.h
+++ b/gfx/layers/CanvasDrawEventRecorder.h
@@ -21,6 +21,10 @@ namespace mozilla {
using EventType = gfx::RecordedEvent::EventType;
+namespace dom {
+class ThreadSafeWorkerRef;
+}
+
namespace layers {
typedef mozilla::ipc::SharedMemoryBasic::Handle Handle;
@@ -31,7 +35,8 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(CanvasDrawEventRecorder, final)
- CanvasDrawEventRecorder();
+ explicit CanvasDrawEventRecorder(dom::ThreadSafeWorkerRef* aWorkerRef);
+ ~CanvasDrawEventRecorder() override;
enum class State : uint32_t {
Processing,
@@ -68,6 +73,7 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
virtual ~Helpers() = default;
virtual bool InitTranslator(TextureType aTextureType,
+ TextureType aWebglTextureType,
gfx::BackendType aBackendType,
Handle&& aReadHandle,
nsTArray<Handle>&& aBufferHandles,
@@ -89,8 +95,8 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
virtual bool RestartReader() = 0;
};
- bool Init(TextureType aTextureType, gfx::BackendType aBackendType,
- UniquePtr<Helpers> aHelpers);
+ bool Init(TextureType aTextureType, TextureType aWebglTextureType,
+ gfx::BackendType aBackendType, UniquePtr<Helpers> aHelpers);
/**
* Record an event for processing by the CanvasParent's CanvasTranslator.
@@ -98,6 +104,10 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
*/
void RecordEvent(const gfx::RecordedEvent& aEvent) final;
+ void DetachResources() final;
+
+ void AddPendingDeletion(std::function<void()>&& aPendingDeletion) override;
+
void StoreSourceSurfaceRecording(gfx::SourceSurface* aSurface,
const char* aReason) final;
@@ -134,6 +144,11 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
void CheckAndSignalReader();
+ void QueueProcessPendingDeletions(
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder);
+ void QueueProcessPendingDeletionsLocked(
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder);
+
size_t mDefaultBufferSize;
size_t mMaxDefaultBuffers;
uint32_t mMaxSpinCount;
@@ -173,6 +188,9 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
+
+ RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
+ bool mIsOnWorker = false;
};
} // namespace layers
diff --git a/gfx/layers/FrameMetrics.cpp b/gfx/layers/FrameMetrics.cpp
index 5d82b7f295..86fdd5ffd6 100644
--- a/gfx/layers/FrameMetrics.cpp
+++ b/gfx/layers/FrameMetrics.cpp
@@ -147,12 +147,10 @@ CSSSize FrameMetrics::CalculateCompositedSizeInCssPixels(
return aCompositionBounds.Size() / aZoom;
}
-std::pair<bool, CSSPoint> FrameMetrics::ApplyAbsoluteScrollUpdateFrom(
- const ScrollPositionUpdate& aUpdate) {
- CSSPoint oldVisualOffset = GetVisualScrollOffset();
+bool FrameMetrics::ApplyScrollUpdateFrom(const ScrollPositionUpdate& aUpdate) {
// In applying a main-thread scroll update, try to preserve the relative
// offset between the visual and layout viewports.
- CSSPoint relativeOffset = oldVisualOffset - GetLayoutScrollOffset();
+ CSSPoint relativeOffset = GetVisualScrollOffset() - GetLayoutScrollOffset();
MOZ_ASSERT(IsRootContent() || relativeOffset == CSSPoint());
// We need to set the two offsets together, otherwise a subsequent
// RecalculateLayoutViewportOffset() could see divergent layout and
@@ -160,7 +158,7 @@ std::pair<bool, CSSPoint> FrameMetrics::ApplyAbsoluteScrollUpdateFrom(
bool offsetChanged = SetLayoutScrollOffset(aUpdate.GetDestination());
offsetChanged |=
ClampAndSetVisualScrollOffset(aUpdate.GetDestination() + relativeOffset);
- return {offsetChanged, GetVisualScrollOffset() - oldVisualOffset};
+ return offsetChanged;
}
CSSPoint FrameMetrics::ApplyRelativeScrollUpdateFrom(
@@ -168,7 +166,7 @@ CSSPoint FrameMetrics::ApplyRelativeScrollUpdateFrom(
MOZ_ASSERT(aUpdate.GetType() == ScrollUpdateType::Relative);
CSSPoint origin = GetVisualScrollOffset();
CSSPoint delta = (aUpdate.GetDestination() - aUpdate.GetSource());
- ClampAndSetVisualScrollOffset(origin + delta);
+ SetVisualScrollOffset(origin + delta);
return GetVisualScrollOffset() - origin;
}
diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h
index 6b7a41bf25..5d13d36703 100644
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -243,11 +243,9 @@ struct FrameMetrics {
}
/*
- * Returns true if the layout scroll offset or visual scroll offset changed
- * and returns the visual scroll offset change delta.
+ * Returns true if the layout scroll offset or visual scroll offset changed.
*/
- std::pair<bool, CSSPoint> ApplyAbsoluteScrollUpdateFrom(
- const ScrollPositionUpdate& aUpdate);
+ bool ApplyScrollUpdateFrom(const ScrollPositionUpdate& aUpdate);
/**
* Applies the relative scroll offset update contained in aOther to the
@@ -893,6 +891,12 @@ struct ScrollMetadata {
mScrollUpdates.AppendElements(std::move(aUpdates));
}
+ void PrependUpdates(const nsTArray<ScrollPositionUpdate>& aUpdates) {
+ MOZ_ASSERT(!aUpdates.IsEmpty());
+
+ mScrollUpdates.InsertElementsAt(0, aUpdates);
+ }
+
private:
FrameMetrics mMetrics;
diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp
index 8a4c03f5a2..bdedccf56d 100644
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -34,7 +34,7 @@
#include "nsProxyRelease.h"
#include "nsISupportsUtils.h" // for NS_IF_ADDREF
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
# include "MacIOSurfaceImage.h"
#endif
@@ -563,7 +563,7 @@ ImageContainer::GetD3D11YCbCrRecycleAllocator(
}
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
already_AddRefed<MacIOSurfaceRecycleAllocator>
ImageContainer::GetMacIOSurfaceRecycleAllocator() {
RecursiveMutexAutoLock lock(mRecursiveMutex);
diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h
index 253ba417eb..6fa12cf195 100644
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -63,7 +63,7 @@ class MemoryOrShmem;
class D3D11RecycleAllocator;
class D3D11YCbCrRecycleAllocator;
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
class MacIOSurfaceRecycleAllocator;
#endif
class SurfaceDescriptorBuffer;
@@ -80,7 +80,7 @@ class GLImage;
class SharedRGBImage;
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureImage;
-#elif defined(XP_MACOSX)
+#elif defined(XP_DARWIN)
class MacIOSurfaceImage;
#elif MOZ_WIDGET_GTK
class DMABUFSurfaceImage;
@@ -159,7 +159,7 @@ class Image {
#ifdef MOZ_WIDGET_ANDROID
virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
virtual MacIOSurfaceImage* AsMacIOSurfaceImage() { return nullptr; }
#endif
virtual PlanarYCbCrImage* AsPlanarYCbCrImage() { return nullptr; }
@@ -191,8 +191,8 @@ class Image {
virtual ~Image() = default;
mozilla::EnumeratedArray<mozilla::layers::LayersBackend,
- mozilla::layers::LayersBackend::LAYERS_LAST,
- UniquePtr<ImageBackendData>>
+ UniquePtr<ImageBackendData>,
+ size_t(mozilla::layers::LayersBackend::LAYERS_LAST)>
mBackendData;
void* mImplData;
@@ -530,7 +530,7 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
KnowsCompositor* aKnowsCompositor);
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
already_AddRefed<MacIOSurfaceRecycleAllocator>
GetMacIOSurfaceRecycleAllocator();
#endif
@@ -618,7 +618,7 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
RefPtr<D3D11YCbCrRecycleAllocator> mD3D11YCbCrRecycleAllocator
MOZ_GUARDED_BY(mRecursiveMutex);
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
RefPtr<MacIOSurfaceRecycleAllocator> mMacIOSurfaceRecycleAllocator
MOZ_GUARDED_BY(mRecursiveMutex);
#endif
diff --git a/gfx/layers/NativeLayerCA.h b/gfx/layers/NativeLayerCA.h
index 1424c1251f..b41ac36c23 100644
--- a/gfx/layers/NativeLayerCA.h
+++ b/gfx/layers/NativeLayerCA.h
@@ -6,7 +6,7 @@
#ifndef mozilla_layers_NativeLayerCA_h
#define mozilla_layers_NativeLayerCA_h
-#include <IOSurface/IOSurface.h>
+#include <IOSurface/IOSurfaceRef.h>
#include <deque>
#include <unordered_map>
@@ -39,7 +39,9 @@ class RenderMacIOSurfaceTextureHost;
namespace layers {
+#ifdef XP_MACOSX
class NativeLayerRootSnapshotterCA;
+#endif
class SurfacePoolHandleCA;
enum class VideoLowPowerType {
@@ -102,8 +104,10 @@ class NativeLayerRootCA : public NativeLayerRoot {
bool CommitToScreen() override;
void CommitOffscreen();
+#ifdef XP_MACOSX
void OnNativeLayerRootSnapshotterDestroyed(
NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter);
+#endif
// Enters a mode during which CommitToScreen(), when called on a non-main
// thread, will not apply any updates to the CALayer tree.
@@ -139,7 +143,7 @@ class NativeLayerRootCA : public NativeLayerRoot {
void SetWindowIsFullscreen(bool aFullscreen);
- VideoLowPowerType CheckVideoLowPower(const MutexAutoLock& aProofOfLock);
+ VideoLowPowerType CheckVideoLowPower();
protected:
explicit NativeLayerRootCA(CALayer* aLayer);
@@ -149,7 +153,8 @@ class NativeLayerRootCA : public NativeLayerRoot {
explicit Representation(CALayer* aRootCALayer);
~Representation();
void Commit(WhichRepresentation aRepresentation,
- const nsTArray<RefPtr<NativeLayerCA>>& aSublayers);
+ const nsTArray<RefPtr<NativeLayerCA>>& aSublayers,
+ bool aWindowIsFullscreen);
CALayer* mRootCALayer = nullptr; // strong
bool mMutatedLayerStructure = false;
};
@@ -160,7 +165,9 @@ class NativeLayerRootCA : public NativeLayerRoot {
Mutex mMutex MOZ_UNANNOTATED; // protects all other fields
Representation mOnscreenRepresentation;
Representation mOffscreenRepresentation;
+#ifdef XP_MACOSX
NativeLayerRootSnapshotterCA* mWeakSnapshotter = nullptr;
+#endif
nsTArray<RefPtr<NativeLayerCA>> mSublayers; // in z-order
float mBackingScale = 1.0f;
bool mMutated = false;
@@ -188,6 +195,7 @@ class NativeLayerRootCA : public NativeLayerRoot {
class RenderSourceNLRS;
+#ifdef XP_MACOSX
class NativeLayerRootSnapshotterCA final : public NativeLayerRootSnapshotter {
public:
static UniquePtr<NativeLayerRootSnapshotterCA> Create(
@@ -217,6 +225,7 @@ class NativeLayerRootSnapshotterCA final : public NativeLayerRootSnapshotter {
RefPtr<RenderSourceNLRS> mSnapshot;
CARenderer* mRenderer = nullptr; // strong
};
+#endif
// NativeLayerCA wraps a CALayer and lets you draw to it. It ensures that only
// fully-drawn frames make their way to the screen, by maintaining a swap chain
@@ -260,6 +269,8 @@ class NativeLayerCA : public NativeLayer {
void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
+ void SetRootWindowIsFullscreen(bool aFullscreen);
+
protected:
friend class NativeLayerRootCA;
@@ -324,7 +335,8 @@ class NativeLayerCA : public NativeLayer {
Maybe<SurfaceWithInvalidRegion> GetUnusedSurfaceAndCleanUp(
const MutexAutoLock& aProofOfLock);
- bool IsVideo(const MutexAutoLock& aProofOfLock);
+ bool IsVideo();
+ bool IsVideoAndLocked(const MutexAutoLock& aProofOfLock);
bool ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock);
bool HasExtent() const { return mHasExtent; }
void SetHasExtent(bool aHasExtent) { mHasExtent = aHasExtent; }
@@ -468,10 +480,10 @@ class NativeLayerCA : public NativeLayer {
bool mSurfaceIsFlipped = false;
CFTypeRefPtr<CGColorRef> mColor;
const bool mIsOpaque = false;
+ bool mRootWindowIsFullscreen = false;
bool mSpecializeVideo = false;
bool mHasExtent = false;
bool mIsDRM = false;
- bool mIsTextureHostVideo = false;
#ifdef NIGHTLY_BUILD
// Track the consistency of our caller's API usage. Layers that are drawn
diff --git a/gfx/layers/NativeLayerCA.mm b/gfx/layers/NativeLayerCA.mm
index bd0b50e91b..42a889184e 100644
--- a/gfx/layers/NativeLayerCA.mm
+++ b/gfx/layers/NativeLayerCA.mm
@@ -5,10 +5,12 @@
#include "mozilla/layers/NativeLayerCA.h"
-#import <AppKit/NSAnimationContext.h>
-#import <AppKit/NSColor.h>
+#ifdef XP_MACOSX
+# import <AppKit/NSAnimationContext.h>
+# import <AppKit/NSColor.h>
+# import <OpenGL/gl.h>
+#endif
#import <AVFoundation/AVFoundation.h>
-#import <OpenGL/gl.h>
#import <QuartzCore/QuartzCore.h>
#include <algorithm>
@@ -19,7 +21,11 @@
#include "gfxUtils.h"
#include "GLBlitHelper.h"
-#include "GLContextCGL.h"
+#ifdef XP_MACOSX
+# include "GLContextCGL.h"
+#else
+# include "GLContextEAGL.h"
+#endif
#include "GLContextProvider.h"
#include "MozFramebuffer.h"
#include "mozilla/gfx/Swizzle.h"
@@ -45,7 +51,9 @@ using gfx::IntSize;
using gfx::Matrix4x4;
using gfx::SurfaceFormat;
using gl::GLContext;
+#ifdef XP_MACOSX
using gl::GLContextCGL;
+#endif
static Maybe<Telemetry::LABELS_GFX_MACOS_VIDEO_LOW_POWER>
VideoLowPowerTypeToTelemetryType(VideoLowPowerType aVideoLowPower) {
@@ -150,13 +158,23 @@ class AsyncReadbackBufferNLRS
// protection, see bug 1585523.
struct MOZ_STACK_CLASS AutoCATransaction final {
AutoCATransaction() {
+#ifdef XP_MACOSX
[NSAnimationContext beginGrouping];
+#else
+ [CATransaction begin];
+#endif
// By default, mutating a CALayer property triggers an animation which
// smoothly transitions the property to the new value. We don't need these
// animations, and this call turns them off:
[CATransaction setDisableActions:YES];
}
- ~AutoCATransaction() { [NSAnimationContext endGrouping]; }
+ ~AutoCATransaction() {
+#ifdef XP_MACOSX
+ [NSAnimationContext endGrouping];
+#else
+ [CATransaction commit];
+#endif
+ }
};
/* static */ already_AddRefed<NativeLayerRootCA>
@@ -178,9 +196,9 @@ static CALayer* MakeOffscreenRootCALayer() {
// down).
AutoCATransaction transaction;
CALayer* layer = [CALayer layer];
- layer.position = NSZeroPoint;
- layer.bounds = NSZeroRect;
- layer.anchorPoint = NSZeroPoint;
+ layer.position = CGPointZero;
+ layer.bounds = CGRectZero;
+ layer.anchorPoint = CGPointZero;
layer.contentsGravity = kCAGravityTopLeft;
layer.masksToBounds = YES;
layer.geometryFlipped = YES;
@@ -226,6 +244,7 @@ void NativeLayerRootCA::AppendLayer(NativeLayer* aLayer) {
mSublayers.AppendElement(layerCA);
layerCA->SetBackingScale(mBackingScale);
+ layerCA->SetRootWindowIsFullscreen(mWindowIsFullscreen);
ForAllRepresentations(
[&](Representation& r) { r.mMutatedLayerStructure = true; });
}
@@ -257,6 +276,7 @@ void NativeLayerRootCA::SetLayers(
RefPtr<NativeLayerCA> layerCA = layer->AsNativeLayerCA();
MOZ_RELEASE_ASSERT(layerCA);
layerCA->SetBackingScale(mBackingScale);
+ layerCA->SetRootWindowIsFullscreen(mWindowIsFullscreen);
layersCA.AppendElement(std::move(layerCA));
}
@@ -306,47 +326,48 @@ bool NativeLayerRootCA::CommitToScreen() {
return false;
}
- mOnscreenRepresentation.Commit(WhichRepresentation::ONSCREEN, mSublayers);
+ mOnscreenRepresentation.Commit(WhichRepresentation::ONSCREEN, mSublayers,
+ mWindowIsFullscreen);
mCommitPending = false;
+ }
- if (StaticPrefs::gfx_webrender_debug_dump_native_layer_tree_to_file()) {
- static uint32_t sFrameID = 0;
- uint32_t frameID = sFrameID++;
-
- NSString* dirPath =
- [NSString stringWithFormat:@"%@/Desktop/nativelayerdumps-%d",
- NSHomeDirectory(), getpid()];
- if ([NSFileManager.defaultManager createDirectoryAtPath:dirPath
- withIntermediateDirectories:YES
- attributes:nil
- error:nullptr]) {
- NSString* filename =
- [NSString stringWithFormat:@"frame-%d.html", frameID];
- NSString* filePath = [dirPath stringByAppendingPathComponent:filename];
- DumpLayerTreeToFile([filePath UTF8String]);
- } else {
- NSLog(@"Failed to create directory %@", dirPath);
- }
+ if (StaticPrefs::gfx_webrender_debug_dump_native_layer_tree_to_file()) {
+ static uint32_t sFrameID = 0;
+ uint32_t frameID = sFrameID++;
+
+ NSString* dirPath =
+ [NSString stringWithFormat:@"%@/Desktop/nativelayerdumps-%d",
+ NSHomeDirectory(), getpid()];
+ if ([NSFileManager.defaultManager createDirectoryAtPath:dirPath
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:nullptr]) {
+ NSString* filename =
+ [NSString stringWithFormat:@"frame-%d.html", frameID];
+ NSString* filePath = [dirPath stringByAppendingPathComponent:filename];
+ DumpLayerTreeToFile([filePath UTF8String]);
+ } else {
+ NSLog(@"Failed to create directory %@", dirPath);
}
+ }
- // Decide if we are going to emit telemetry about video low power on this
- // commit.
- static const int32_t TELEMETRY_COMMIT_PERIOD =
- StaticPrefs::gfx_core_animation_low_power_telemetry_frames_AtStartup();
- mTelemetryCommitCount =
- (mTelemetryCommitCount + 1) % TELEMETRY_COMMIT_PERIOD;
- if (mTelemetryCommitCount == 0) {
- // Figure out if we are hitting video low power mode.
- VideoLowPowerType videoLowPower = CheckVideoLowPower(lock);
- EmitTelemetryForVideoLowPower(videoLowPower);
- }
+ // Decide if we are going to emit telemetry about video low power on this
+ // commit.
+ static const int32_t TELEMETRY_COMMIT_PERIOD =
+ StaticPrefs::gfx_core_animation_low_power_telemetry_frames_AtStartup();
+ mTelemetryCommitCount = (mTelemetryCommitCount + 1) % TELEMETRY_COMMIT_PERIOD;
+ if (mTelemetryCommitCount == 0) {
+ // Figure out if we are hitting video low power mode.
+ VideoLowPowerType videoLowPower = CheckVideoLowPower();
+ EmitTelemetryForVideoLowPower(videoLowPower);
}
return true;
}
UniquePtr<NativeLayerRootSnapshotter> NativeLayerRootCA::CreateSnapshotter() {
+#ifdef XP_MACOSX
MutexAutoLock lock(mMutex);
MOZ_RELEASE_ASSERT(!mWeakSnapshotter,
"No NativeLayerRootSnapshotter for this NativeLayerRoot "
@@ -358,18 +379,24 @@ UniquePtr<NativeLayerRootSnapshotter> NativeLayerRootCA::CreateSnapshotter() {
mWeakSnapshotter = cr.get();
}
return cr;
+#else
+ return nullptr;
+#endif
}
+#ifdef XP_MACOSX
void NativeLayerRootCA::OnNativeLayerRootSnapshotterDestroyed(
NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter) {
MutexAutoLock lock(mMutex);
MOZ_RELEASE_ASSERT(mWeakSnapshotter == aNativeLayerRootSnapshotter);
mWeakSnapshotter = nullptr;
}
+#endif
void NativeLayerRootCA::CommitOffscreen() {
MutexAutoLock lock(mMutex);
- mOffscreenRepresentation.Commit(WhichRepresentation::OFFSCREEN, mSublayers);
+ mOffscreenRepresentation.Commit(WhichRepresentation::OFFSCREEN, mSublayers,
+ mWindowIsFullscreen);
}
template <typename F>
@@ -394,7 +421,8 @@ NativeLayerRootCA::Representation::~Representation() {
void NativeLayerRootCA::Representation::Commit(
WhichRepresentation aRepresentation,
- const nsTArray<RefPtr<NativeLayerCA>>& aSublayers) {
+ const nsTArray<RefPtr<NativeLayerCA>>& aSublayers,
+ bool aWindowIsFullscreen) {
bool mustRebuild = mMutatedLayerStructure;
if (!mustRebuild) {
// Check which type of update we need to do, if any.
@@ -439,7 +467,7 @@ void NativeLayerRootCA::Representation::Commit(
mustRebuild |= layer->WillUpdateAffectLayers(aRepresentation);
layer->ApplyChanges(aRepresentation, NativeLayerCA::UpdateType::All);
CALayer* caLayer = layer->UnderlyingCALayer(aRepresentation);
- if (!caLayer.masksToBounds || !NSIsEmptyRect(caLayer.bounds)) {
+ if (!caLayer.masksToBounds || !CGRectIsEmpty(caLayer.bounds)) {
// This layer has an extent. If it didn't before, we need to rebuild.
mustRebuild |= !layer->HasExtent();
layer->SetHasExtent(true);
@@ -472,6 +500,7 @@ void NativeLayerRootCA::Representation::Commit(
mMutatedLayerStructure = false;
}
+#ifdef XP_MACOSX
/* static */ UniquePtr<NativeLayerRootSnapshotterCA>
NativeLayerRootSnapshotterCA::Create(NativeLayerRootCA* aLayerRoot,
CALayer* aRootCALayer) {
@@ -498,6 +527,7 @@ NativeLayerRootSnapshotterCA::Create(NativeLayerRootCA* aLayerRoot,
new NativeLayerRootSnapshotterCA(aLayerRoot, std::move(gl),
aRootCALayer));
}
+#endif
void NativeLayerRootCA::DumpLayerTreeToFile(const char* aPath) {
MutexAutoLock lock(mMutex);
@@ -519,7 +549,15 @@ void NativeLayerRootCA::DumpLayerTreeToFile(const char* aPath) {
}
void NativeLayerRootCA::SetWindowIsFullscreen(bool aFullscreen) {
- mWindowIsFullscreen = aFullscreen;
+ MutexAutoLock lock(mMutex);
+
+ if (mWindowIsFullscreen != aFullscreen) {
+ mWindowIsFullscreen = aFullscreen;
+
+ for (auto layer : mSublayers) {
+ layer->SetRootWindowIsFullscreen(mWindowIsFullscreen);
+ }
+ }
}
/* static */ bool IsCGColorOpaqueBlack(CGColorRef aColor) {
@@ -541,8 +579,7 @@ void NativeLayerRootCA::SetWindowIsFullscreen(bool aFullscreen) {
return components[componentCount - 1] >= 1.0f;
}
-VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower(
- const MutexAutoLock& aProofOfLock) {
+VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower() {
// This deteremines whether the current layer contents qualify for the
// macOS Core Animation video low power mode. Those requirements are
// summarized at
@@ -572,7 +609,7 @@ VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower(
secondCALayer = topCALayer;
topCALayer = topLayer->UnderlyingCALayer(WhichRepresentation::ONSCREEN);
- topLayerIsVideo = topLayer->IsVideo(aProofOfLock);
+ topLayerIsVideo = topLayer->IsVideo();
if (topLayerIsVideo) {
++videoLayerCount;
}
@@ -641,6 +678,7 @@ VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower(
return VideoLowPowerType::LowPower;
}
+#ifdef XP_MACOSX
NativeLayerRootSnapshotterCA::NativeLayerRootSnapshotterCA(
NativeLayerRootCA* aLayerRoot, RefPtr<GLContext>&& aGL,
CALayer* aRootCALayer)
@@ -779,6 +817,7 @@ NativeLayerRootSnapshotterCA::CreateAsyncReadbackBuffer(const IntSize& aSize) {
LOCAL_GL_STREAM_READ);
return MakeAndAddRef<AsyncReadbackBufferNLRS>(mGL, aSize, bufferHandle);
}
+#endif
NativeLayerCA::NativeLayerCA(const IntSize& aSize, bool aIsOpaque,
SurfacePoolHandleCA* aSurfacePoolHandle)
@@ -796,8 +835,9 @@ NativeLayerCA::NativeLayerCA(bool aIsOpaque)
mIsOpaque(aIsOpaque) {
#ifdef NIGHTLY_BUILD
if (StaticPrefs::gfx_core_animation_specialize_video_log()) {
- NSLog(@"VIDEO_LOG: NativeLayerCA: %p is being created to host an external "
- @"image, which may force a video layer rebuild.",
+ NSLog(@"VIDEO_LOG: NativeLayerCA: %p is being created to host video, which "
+ @"will force a video "
+ @"layer rebuild.",
this);
}
#endif
@@ -824,7 +864,7 @@ NativeLayerCA::~NativeLayerCA() {
if (mHasEverAttachExternalImage &&
StaticPrefs::gfx_core_animation_specialize_video_log()) {
NSLog(@"VIDEO_LOG: ~NativeLayerCA: %p is being destroyed after hosting "
- @"an external image.",
+ @"video.",
this);
}
#endif
@@ -862,9 +902,6 @@ void NativeLayerCA::AttachExternalImage(wr::RenderTextureHost* aExternalImage) {
return;
}
- // Determine if TextureHost is a video surface.
- mIsTextureHostVideo = gfx::Info(mTextureHost->GetFormat())->isYuv;
-
gfx::IntSize oldSize = mSize;
mSize = texture->GetSize(0);
bool changedSizeAndDisplayRect = (mSize != oldSize);
@@ -896,15 +933,18 @@ void NativeLayerCA::AttachExternalImage(wr::RenderTextureHost* aExternalImage) {
});
}
-bool NativeLayerCA::IsVideo(const MutexAutoLock& aProofOfLock) {
- // If we have a texture host, we've checked to see if it's providing video.
- // And if we don't have a texture host, it isn't video, so we just check
- // the value we've computed.
- return mIsTextureHostVideo;
+bool NativeLayerCA::IsVideo() {
+ // Anything with a texture host is considered a video source.
+ return mTextureHost;
+}
+
+bool NativeLayerCA::IsVideoAndLocked(const MutexAutoLock& aProofOfLock) {
+ // Anything with a texture host is considered a video source.
+ return mTextureHost;
}
bool NativeLayerCA::ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock) {
- if (!IsVideo(aProofOfLock)) {
+ if (!IsVideoAndLocked(aProofOfLock)) {
// Only videos are eligible.
return false;
}
@@ -934,7 +974,49 @@ bool NativeLayerCA::ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock) {
return true;
}
- return StaticPrefs::gfx_core_animation_specialize_video();
+ // Beyond this point, we return true if-and-only-if we think we can achieve
+ // the power-saving "detached mode" of the macOS compositor.
+
+ if (!StaticPrefs::gfx_core_animation_specialize_video()) {
+ // Pref must be set.
+ return false;
+ }
+
+ if (pixelFormat != kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange &&
+ pixelFormat != kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
+ // The video is not in one of the formats that qualifies for detachment.
+ return false;
+ }
+
+ // It will only detach if we're fullscreen.
+ return mRootWindowIsFullscreen;
+}
+
+void NativeLayerCA::SetRootWindowIsFullscreen(bool aFullscreen) {
+ if (mRootWindowIsFullscreen == aFullscreen) {
+ return;
+ }
+
+ MutexAutoLock lock(mMutex);
+
+ mRootWindowIsFullscreen = aFullscreen;
+
+ bool oldSpecializeVideo = mSpecializeVideo;
+ mSpecializeVideo = ShouldSpecializeVideo(lock);
+ bool changedSpecializeVideo = (mSpecializeVideo != oldSpecializeVideo);
+
+ if (changedSpecializeVideo) {
+#ifdef NIGHTLY_BUILD
+ if (StaticPrefs::gfx_core_animation_specialize_video_log()) {
+ NSLog(@"VIDEO_LOG: SetRootWindowIsFullscreen: %p is forcing a video "
+ @"layer rebuild.",
+ this);
+ }
+#endif
+
+ ForAllRepresentations(
+ [&](Representation& r) { r.mMutatedSpecializeVideo = true; });
+ }
}
void NativeLayerCA::SetSurfaceIsFlipped(bool aIsFlipped) {
@@ -1328,8 +1410,6 @@ void NativeLayerCA::NotifySurfaceReady() {
mInProgressSurface,
"NotifySurfaceReady called without preceding call to NextSurface");
- mIsTextureHostVideo = false;
-
if (mInProgressLockedIOSurface) {
mInProgressLockedIOSurface->Unlock(false);
mInProgressLockedIOSurface = nullptr;
@@ -1385,7 +1465,7 @@ void NativeLayerCA::ForAllRepresentations(F aFn) {
NativeLayerCA::UpdateType NativeLayerCA::HasUpdate(
WhichRepresentation aRepresentation) {
MutexAutoLock lock(mMutex);
- return GetRepresentation(aRepresentation).HasUpdate(IsVideo(lock));
+ return GetRepresentation(aRepresentation).HasUpdate(IsVideoAndLocked(lock));
}
/* static */
@@ -1430,7 +1510,7 @@ bool NativeLayerCA::ApplyChanges(WhichRepresentation aRepresentation,
.ApplyChanges(aUpdate, mSize, mIsOpaque, mPosition, mTransform,
mDisplayRect, mClipRect, mBackingScale, mSurfaceIsFlipped,
mSamplingFilter, mSpecializeVideo, surface, mColor, mIsDRM,
- IsVideo(lock));
+ IsVideo());
}
CALayer* NativeLayerCA::UnderlyingCALayer(WhichRepresentation aRepresentation) {
@@ -1457,8 +1537,10 @@ static NSString* NSStringForOSType(OSType type) {
CFRelease(surfaceValues);
if (aBuffer) {
+#ifdef XP_MACOSX
CGColorSpaceRef colorSpace = CVImageBufferGetColorSpace(aBuffer);
NSLog(@"ColorSpace is %@.\n", colorSpace);
+#endif
CFDictionaryRef bufferAttachments =
CVBufferGetAttachments(aBuffer, kCVAttachmentMode_ShouldPropagate);
@@ -1512,7 +1594,7 @@ bool NativeLayerCA::Representation::EnqueueSurface(IOSurfaceRef aSurfaceRef) {
return false;
}
-#ifdef NIGHTLY_BUILD
+#if defined(NIGHTLY_BUILD) && defined(XP_MACOSX)
if (StaticPrefs::gfx_core_animation_specialize_video_check_color_space()) {
// Ensure the resulting pixel buffer has a color space. If it doesn't, then
// modify the surface and create the buffer again.
@@ -1764,10 +1846,10 @@ bool NativeLayerCA::Representation::ApplyChanges(
mOpaquenessTintLayer.contentsGravity = kCAGravityTopLeft;
if (aIsOpaque) {
mOpaquenessTintLayer.backgroundColor =
- [[[NSColor greenColor] colorWithAlphaComponent:0.5] CGColor];
+ CGColorCreateGenericRGB(0, 1, 0, 0.5);
} else {
mOpaquenessTintLayer.backgroundColor =
- [[[NSColor redColor] colorWithAlphaComponent:0.5] CGColor];
+ CGColorCreateGenericRGB(1, 0, 0, 0.5);
}
[mWrappingCALayer addSublayer:mOpaquenessTintLayer];
} else if (!shouldTintOpaqueness && mOpaquenessTintLayer) {
diff --git a/gfx/layers/PersistentBufferProvider.cpp b/gfx/layers/PersistentBufferProvider.cpp
index 0e02501a4a..d79c8cdca1 100644
--- a/gfx/layers/PersistentBufferProvider.cpp
+++ b/gfx/layers/PersistentBufferProvider.cpp
@@ -663,14 +663,15 @@ PersistentBufferProviderShared::BorrowSnapshot(gfx::DrawTarget* aTarget) {
if (mDrawTarget) {
auto back = GetTexture(mBack);
- MOZ_ASSERT(back && back->IsLocked());
+ if (NS_WARN_IF(!back) || NS_WARN_IF(!back->IsLocked())) {
+ return nullptr;
+ }
mSnapshot = back->BorrowSnapshot();
return do_AddRef(mSnapshot);
}
auto front = GetTexture(mFront);
- if (!front || front->IsLocked()) {
- MOZ_ASSERT(false);
+ if (NS_WARN_IF(!front) || NS_WARN_IF(front->IsLocked())) {
return nullptr;
}
diff --git a/gfx/layers/RemoteTextureMap.cpp b/gfx/layers/RemoteTextureMap.cpp
index fa0cfd33f5..3fe3b13deb 100644
--- a/gfx/layers/RemoteTextureMap.cpp
+++ b/gfx/layers/RemoteTextureMap.cpp
@@ -369,7 +369,11 @@ void RemoteTextureMap::PushTexture(
aTextureId, aTextureHost, std::move(aTextureData),
std::move(aResourceWrapper));
- MOZ_ASSERT(owner->mLatestTextureId < aTextureId);
+ MOZ_ASSERT(owner->mLatestPushedTextureId < aTextureId);
+ if (owner->mLatestPushedTextureId < aTextureId) {
+ owner->mLatestPushedTextureId = aTextureId;
+ }
+ MOZ_ASSERT(owner->mLatestUsingTextureId < aTextureId);
owner->mWaitingTextureDataHolders.push_back(std::move(textureData));
@@ -898,9 +902,9 @@ void RemoteTextureMap::UpdateTexture(const MonitorAutoLock& aProofOfLock,
const RemoteTextureId aTextureId) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(aOwner);
- MOZ_ASSERT(aTextureId >= aOwner->mLatestTextureId);
+ MOZ_ASSERT(aTextureId >= aOwner->mLatestUsingTextureId);
- if (aTextureId == aOwner->mLatestTextureId) {
+ if (aTextureId == aOwner->mLatestUsingTextureId) {
// No need to update texture.
return;
}
@@ -913,7 +917,7 @@ void RemoteTextureMap::UpdateTexture(const MonitorAutoLock& aProofOfLock,
}
MOZ_RELEASE_ASSERT(front->mTextureHost);
aOwner->mLatestTextureHost = front->mTextureHost;
- aOwner->mLatestTextureId = front->mTextureId;
+ aOwner->mLatestUsingTextureId = front->mTextureId;
UniquePtr<TextureDataHolder> holder = std::move(front);
aOwner->mWaitingTextureDataHolders.pop_front();
@@ -962,10 +966,42 @@ void RemoteTextureMap::GetAllRenderingReadyCallbacks(
MOZ_ASSERT(aOwner->mRenderingReadyCallbackHolders.empty());
}
+bool RemoteTextureMap::WaitForRemoteTextureOwner(
+ RemoteTextureHostWrapper* aTextureHostWrapper) {
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ MOZ_ASSERT(aTextureHostWrapper);
+
+ const auto& ownerId = aTextureHostWrapper->mOwnerId;
+ const auto& forPid = aTextureHostWrapper->mForPid;
+
+ MonitorAutoLock lock(mMonitor);
+
+ auto* owner = GetTextureOwner(lock, ownerId, forPid);
+ // If there is no texture owner yet, then we might need to wait for one to
+ // be created, if allowed. If so, we must also wait for an initial texture
+ // host to be created so we can use it.
+ if (!owner || (!owner->mLatestTextureHost &&
+ owner->mWaitingTextureDataHolders.empty())) {
+ const TimeDuration timeout = TimeDuration::FromMilliseconds(10000);
+ while (!owner || (!owner->mLatestTextureHost &&
+ owner->mWaitingTextureDataHolders.empty())) {
+ if (owner && (owner->mIsContextLost || owner->mDeferUnregister)) {
+ // If the context was lost, no further updates are expected.
+ return false;
+ }
+ CVStatus status = mMonitor.Wait(timeout);
+ if (status == CVStatus::Timeout) {
+ return false;
+ }
+ owner = GetTextureOwner(lock, ownerId, forPid);
+ }
+ }
+ return true;
+}
+
bool RemoteTextureMap::GetRemoteTexture(
RemoteTextureHostWrapper* aTextureHostWrapper,
- std::function<void(const RemoteTextureInfo&)>&& aReadyCallback,
- bool aWaitForRemoteTextureOwner) {
+ std::function<void(const RemoteTextureInfo&)>&& aReadyCallback) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(aTextureHostWrapper);
@@ -983,27 +1019,8 @@ bool RemoteTextureMap::GetRemoteTexture(
MonitorAutoLock lock(mMonitor);
auto* owner = GetTextureOwner(lock, ownerId, forPid);
- // If there is no texture owner yet, then we might need to wait for one to
- // be created, if allowed. If so, we must also wait for an initial texture
- // host to be created so we can use it.
- if (!owner || (aWaitForRemoteTextureOwner && !owner->mLatestTextureHost &&
- owner->mWaitingTextureDataHolders.empty())) {
- if (!aWaitForRemoteTextureOwner) {
- return false;
- }
- const TimeDuration timeout = TimeDuration::FromMilliseconds(10000);
- while (!owner || (!owner->mLatestTextureHost &&
- owner->mWaitingTextureDataHolders.empty())) {
- if (owner && (owner->mIsContextLost || owner->mDeferUnregister)) {
- // If the context was lost, no further updates are expected.
- return false;
- }
- CVStatus status = mMonitor.Wait(timeout);
- if (status == CVStatus::Timeout) {
- return false;
- }
- owner = GetTextureOwner(lock, ownerId, forPid);
- }
+ if (!owner) {
+ return false;
}
UpdateTexture(lock, owner, textureId);
@@ -1014,7 +1031,7 @@ bool RemoteTextureMap::GetRemoteTexture(
return false;
}
- if (textureId == owner->mLatestTextureId) {
+ if (textureId == owner->mLatestUsingTextureId) {
MOZ_ASSERT(owner->mLatestTextureHost);
MOZ_ASSERT(owner->mLatestTextureHost->GetSize() == size);
if (owner->mLatestTextureHost->GetSize() != size) {
@@ -1034,7 +1051,7 @@ bool RemoteTextureMap::GetRemoteTexture(
}
// Update mRemoteTextureHost
- if (textureId == owner->mLatestTextureId) {
+ if (textureId == owner->mLatestUsingTextureId) {
const auto key = std::pair(forPid, textureId);
auto it = mRemoteTextureHostWrapperHolders.find(key);
if (it != mRemoteTextureHostWrapperHolders.end() &&
@@ -1195,16 +1212,9 @@ bool RemoteTextureMap::CheckRemoteTextureReady(
return true;
}
- if (it->second->mRemoteTextureHost) {
+ if (owner->mLatestPushedTextureId >= aInfo.mTextureId) {
return true;
}
- MOZ_ASSERT(!it->second->mRemoteTextureHost);
-
- // Check if RemoteTextureId is as expected.
- if (!owner->mRenderingReadyCallbackHolders.empty()) {
- auto& front = owner->mRenderingReadyCallbackHolders.front();
- MOZ_RELEASE_ASSERT(aInfo.mTextureId >= front->mTextureId);
- }
auto callbackHolder = MakeUnique<RenderingReadyCallbackHolder>(
aInfo.mTextureId, std::move(aCallback));
@@ -1234,9 +1244,8 @@ bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) {
}
const TimeDuration timeout = TimeDuration::FromMilliseconds(1000);
- TextureHost* remoteTexture = it->second->mRemoteTextureHost;
- while (!remoteTexture) {
+ while (owner->mLatestPushedTextureId < aInfo.mTextureId) {
CVStatus status = mMonitor.Wait(timeout);
if (status == CVStatus::Timeout) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
@@ -1251,14 +1260,11 @@ bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) {
return false;
}
- remoteTexture = it->second->mRemoteTextureHost;
- if (!remoteTexture) {
- auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid);
- // When owner is alreay unregistered, remote texture will not be pushed.
- if (!owner || owner->mIsContextLost) {
- // This could happen with IPC abnormal shutdown
- return false;
- }
+ auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid);
+ // When owner is alreay unregistered, remote texture will not be pushed.
+ if (!owner || owner->mIsContextLost) {
+ // This could happen with IPC abnormal shutdown
+ return false;
}
}
diff --git a/gfx/layers/RemoteTextureMap.h b/gfx/layers/RemoteTextureMap.h
index a60bfd4c3c..8aee1c6f7d 100644
--- a/gfx/layers/RemoteTextureMap.h
+++ b/gfx/layers/RemoteTextureMap.h
@@ -304,13 +304,14 @@ class RemoteTextureMap {
void NotifyContextRestored(const RemoteTextureOwnerIdSet& aOwnerIds,
const base::ProcessId aForPid);
+ bool WaitForRemoteTextureOwner(RemoteTextureHostWrapper* aTextureHostWrapper);
+
// Get remote texture's TextureHost for RemoteTextureHostWrapper.
//
// return true when aReadyCallback will be called.
bool GetRemoteTexture(
RemoteTextureHostWrapper* aTextureHostWrapper,
- std::function<void(const RemoteTextureInfo&)>&& aReadyCallback,
- bool aWaitForRemoteTextureOwner = false);
+ std::function<void(const RemoteTextureInfo&)>&& aReadyCallback);
bool WaitForTxn(const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid, RemoteTextureTxnType aTxnType,
@@ -403,7 +404,8 @@ class RemoteTextureMap {
std::deque<UniquePtr<RenderingReadyCallbackHolder>>
mRenderingReadyCallbackHolders;
- RemoteTextureId mLatestTextureId = {0};
+ RemoteTextureId mLatestPushedTextureId = {0};
+ RemoteTextureId mLatestUsingTextureId = {0};
CompositableTextureHostRef mLatestTextureHost;
CompositableTextureHostRef mLatestRenderedTextureHost;
// Holds compositable refs to TextureHosts of RenderTextureHosts that are
diff --git a/gfx/layers/SurfacePool.h b/gfx/layers/SurfacePool.h
index eecb398d85..6be3718af5 100644
--- a/gfx/layers/SurfacePool.h
+++ b/gfx/layers/SurfacePool.h
@@ -31,7 +31,7 @@ class SurfacePool {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SurfacePool);
-#if defined(XP_MACOSX) || defined(MOZ_WAYLAND)
+#if defined(XP_DARWIN) || defined(MOZ_WAYLAND)
static RefPtr<SurfacePool> Create(size_t aPoolSizeLimit);
#endif
diff --git a/gfx/layers/SurfacePoolCA.h b/gfx/layers/SurfacePoolCA.h
index 97344f7d06..265782df9e 100644
--- a/gfx/layers/SurfacePoolCA.h
+++ b/gfx/layers/SurfacePoolCA.h
@@ -6,7 +6,7 @@
#ifndef mozilla_layers_SurfacePoolCA_h
#define mozilla_layers_SurfacePoolCA_h
-#include <IOSurface/IOSurface.h>
+#include <IOSurface/IOSurfaceRef.h>
#include <deque>
#include <unordered_map>
diff --git a/gfx/layers/SurfacePoolCA.mm b/gfx/layers/SurfacePoolCA.mm
index 47b2663ed7..4e012350f0 100644
--- a/gfx/layers/SurfacePoolCA.mm
+++ b/gfx/layers/SurfacePoolCA.mm
@@ -6,6 +6,7 @@
#include "mozilla/layers/SurfacePoolCA.h"
#import <CoreVideo/CVPixelBuffer.h>
+#include <IOSurface/IOSurfaceTypes.h>
#include <algorithm>
#include <unordered_set>
@@ -16,7 +17,12 @@
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPrefs_gfx.h"
-#include "GLContextCGL.h"
+#ifdef XP_MACOSX
+# include "GLContextCGL.h"
+#else
+# include "GLContextEAGL.h"
+#endif
+
#include "MozFramebuffer.h"
#include "ScopedGLHelpers.h"
@@ -28,7 +34,11 @@ using gfx::IntRect;
using gfx::IntRegion;
using gfx::IntSize;
using gl::GLContext;
+#ifdef XP_MACOSX
using gl::GLContextCGL;
+#else
+using gl::GLContextEAGL;
+#endif
/* static */ RefPtr<SurfacePool> SurfacePool::Create(size_t aPoolSizeLimit) {
return new SurfacePoolCA(aPoolSizeLimit);
@@ -306,8 +316,13 @@ Maybe<GLuint> SurfacePoolCA::LockedPool::GetFramebufferForSurface(
"Framebuffer creation", GRAPHICS_TileAllocation,
nsPrintfCString("%dx%d", entry.mSize.width, entry.mSize.height));
+#ifdef XP_MACOSX
RefPtr<GLContextCGL> cgl = GLContextCGL::Cast(aGL);
MOZ_RELEASE_ASSERT(cgl, "Unexpected GLContext type");
+#else
+ RefPtr<GLContextEAGL> eagl = GLContextEAGL::Cast(aGL);
+ MOZ_RELEASE_ASSERT(eagl, "Unexpected GLContext type");
+#endif
if (!aGL->MakeCurrent()) {
// Context may have been destroyed.
@@ -318,10 +333,14 @@ Maybe<GLuint> SurfacePoolCA::LockedPool::GetFramebufferForSurface(
{
const gl::ScopedBindTexture bindTex(aGL, tex,
LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+#ifdef XP_MACOSX
CGLTexImageIOSurface2D(cgl->GetCGLContext(), LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_RGBA, entry.mSize.width, entry.mSize.height,
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
entry.mIOSurface.get(), 0);
+#else
+ MOZ_CRASH("unimplemented");
+#endif
}
auto fb =
diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp
index d28392b716..ef3cde3596 100644
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -62,6 +62,8 @@
mozilla::LazyLogModule mozilla::layers::APZCTreeManager::sLog("apz.manager");
#define APZCTM_LOG(...) \
MOZ_LOG(APZCTreeManager::sLog, LogLevel::Debug, (__VA_ARGS__))
+#define APZCTM_LOGV(...) \
+ MOZ_LOG(APZCTreeManager::sLog, LogLevel::Verbose, (__VA_ARGS__))
static mozilla::LazyLogModule sApzKeyLog("apz.key");
#define APZ_KEY_LOG(...) MOZ_LOG(sApzKeyLog, LogLevel::Debug, (__VA_ARGS__))
@@ -83,10 +85,10 @@ typedef CompositorBridgeParent::LayerTreeState LayerTreeState;
struct APZCTreeManager::TreeBuildingState {
TreeBuildingState(LayersId aRootLayersId, bool aIsFirstPaint,
LayersId aOriginatingLayersId, APZTestData* aTestData,
- uint32_t aPaintSequence)
+ uint32_t aPaintSequence, bool aIsTestLoggingEnabled)
: mIsFirstPaint(aIsFirstPaint),
mOriginatingLayersId(aOriginatingLayersId),
- mPaintLogger(aTestData, aPaintSequence) {
+ mPaintLogger(aTestData, aPaintSequence, aIsTestLoggingEnabled) {
CompositorBridgeParent::CallWithIndirectShadowTree(
aRootLayersId, [this](LayerTreeState& aState) -> void {
mCompositorController = aState.GetCompositorController();
@@ -158,6 +160,9 @@ struct APZCTreeManager::TreeBuildingState {
// cumulative EventRegionsOverride flags from the reflayers, and is used to
// apply them to descendant layers.
std::stack<EventRegionsOverride> mOverrideFlags;
+
+ // Wether the APZC correspoinding to the originating LayersId was updated.
+ bool mOriginatingLayersIdUpdated = false;
};
class APZCTreeManager::CheckerboardFlushObserver : public nsIObserver {
@@ -391,8 +396,7 @@ void APZCTreeManager::SetAllowedTouchBehavior(
uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aValues) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
- NewRunnableMethod<uint64_t,
- StoreCopyPassByLRef<nsTArray<TouchBehaviorFlags>>>(
+ NewRunnableMethod<uint64_t, nsTArray<TouchBehaviorFlags>>(
"layers::APZCTreeManager::SetAllowedTouchBehavior", this,
&APZCTreeManager::SetAllowedTouchBehavior, aInputBlockId,
aValues.Clone()));
@@ -420,9 +424,11 @@ void APZCTreeManager::SetBrowserGestureResponse(
mInputQueue->SetBrowserGestureResponse(aInputBlockId, aResponse);
}
-void APZCTreeManager::UpdateHitTestingTree(
- const WebRenderScrollDataWrapper& aRoot, bool aIsFirstPaint,
- LayersId aOriginatingLayersId, uint32_t aPaintSequenceNumber) {
+APZCTreeManager::OriginatingLayersIdUpdated
+APZCTreeManager::UpdateHitTestingTree(const WebRenderScrollDataWrapper& aRoot,
+ bool aIsFirstPaint,
+ LayersId aOriginatingLayersId,
+ uint32_t aPaintSequenceNumber) {
AssertOnUpdaterThread();
RecursiveMutexAutoLock lock(mTreeLock);
@@ -430,7 +436,8 @@ void APZCTreeManager::UpdateHitTestingTree(
// For testing purposes, we log some data to the APZTestData associated with
// the layers id that originated this update.
APZTestData* testData = nullptr;
- if (StaticPrefs::apz_test_logging_enabled()) {
+ const bool testLoggingEnabled = StaticPrefs::apz_test_logging_enabled();
+ if (testLoggingEnabled) {
MutexAutoLock lock(mTestDataLock);
UniquePtr<APZTestData> ptr = MakeUnique<APZTestData>();
auto result =
@@ -440,7 +447,7 @@ void APZCTreeManager::UpdateHitTestingTree(
}
TreeBuildingState state(mRootLayersId, aIsFirstPaint, aOriginatingLayersId,
- testData, aPaintSequenceNumber);
+ testData, aPaintSequenceNumber, testLoggingEnabled);
// We do this business with collecting the entire tree into an array because
// otherwise it's very hard to determine which APZC instances need to be
@@ -730,6 +737,8 @@ void APZCTreeManager::UpdateHitTestingTree(
mRootNode->Dump(" ");
}
SendSubtreeTransformsToChromeMainThread(nullptr);
+
+ return OriginatingLayersIdUpdated{state.mOriginatingLayersIdUpdated};
}
void APZCTreeManager::UpdateFocusState(LayersId aRootLayerTreeId,
@@ -763,7 +772,7 @@ void APZCTreeManager::SampleForWebRender(const Maybe<VsyncId>& aVsyncId,
controller->ScheduleRenderOnCompositorThread(
wr::RenderReasons::ANIMATED_PROPERTY);
}
- APZCTM_LOG(
+ APZCTM_LOGV(
"APZCTreeManager(%p)::SampleForWebRender, want more composites: %d\n",
this, (activeAnimations && controller));
@@ -1231,6 +1240,10 @@ HitTestingTreeNode* APZCTreeManager::PrepareNodeForLayer(
"Found APZC %p for layer %p with identifiers %" PRIx64 " %" PRId64 "\n",
apzc.get(), aLayer.GetLayer(), uint64_t(guid.mLayersId), guid.mScrollId);
+ if (aLayersId == aState.mOriginatingLayersId) {
+ aState.mOriginatingLayersIdUpdated = true;
+ }
+
// If we haven't encountered a layer already with the same metrics, then we
// need to do the full reuse-or-make-an-APZC algorithm, which is contained
// inside the block below.
@@ -1522,6 +1535,11 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
}
case MOUSE_INPUT: {
MouseInput& mouseInput = aEvent.AsMouseInput();
+ MOZ_LOG(APZCTreeManager::sLog,
+ mouseInput.mType == MouseInput::MOUSE_MOVE ? LogLevel::Verbose
+ : LogLevel::Debug,
+ ("Received mouse input type %d at %s\n", (int)mouseInput.mType,
+ ToString(mouseInput.mOrigin).c_str()));
mouseInput.mHandledByAPZ = true;
SetCurrentMousePosition(mouseInput.mOrigin);
@@ -1613,6 +1631,9 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
// Do this before early return for Fission hit testing.
ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput();
+ APZCTM_LOG("Received wheel input at %s with delta (%f, %f)\n",
+ ToString(wheelInput.mOrigin).c_str(), wheelInput.mDeltaX,
+ wheelInput.mDeltaY);
state.mHit = GetTargetAPZC(wheelInput.mOrigin);
wheelInput.mHandledByAPZ = WillHandleInput(wheelInput);
@@ -1674,6 +1695,9 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
// Do this before early return for Fission hit testing.
PanGestureInput& panInput = aEvent.AsPanGestureInput();
+ APZCTM_LOG("Received pan gesture input type %d at %s with delta %s\n",
+ (int)panInput.mType, ToString(panInput.mPanStartPoint).c_str(),
+ ToString(panInput.mPanDisplacement).c_str());
state.mHit = GetTargetAPZC(panInput.mPanStartPoint);
panInput.mHandledByAPZ = WillHandleInput(panInput);
@@ -2021,6 +2045,18 @@ APZEventResult APZCTreeManager::InputHandlingState::Finish(
void APZCTreeManager::ProcessTouchInput(InputHandlingState& aState,
MultiTouchInput& aInput) {
+ APZCTM_LOG("Received touch input type %d with touch points [%s]\n",
+ (int)aInput.mType,
+ [&] {
+ nsCString result;
+ for (const auto& touch : aInput.mTouches) {
+ result.AppendPrintf("%s",
+ ToString(touch.mScreenPoint).c_str());
+ }
+ return result;
+ }()
+ .get());
+
aInput.mHandledByAPZ = true;
nsTArray<TouchBehaviorFlags> touchBehaviors;
HitTestingTreeNodeAutoLock hitScrollbarNode;
diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h
index ff9bba51ca..71d35fd5a6 100644
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -190,10 +190,13 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
* this layer update. Note that every child
* process' layer subtree has its own sequence
* numbers.
+ * @return OriginatingLayersIdUpdated whether the given
+ * |aOriginatingLayersId|'s data was processed.
*/
- void UpdateHitTestingTree(const WebRenderScrollDataWrapper& aRoot,
- bool aIsFirstPaint, LayersId aOriginatingLayersId,
- uint32_t aPaintSequenceNumber);
+ enum class OriginatingLayersIdUpdated : bool { No, Yes };
+ OriginatingLayersIdUpdated UpdateHitTestingTree(
+ const WebRenderScrollDataWrapper& aRoot, bool aIsFirstPaint,
+ LayersId aOriginatingLayersId, uint32_t aPaintSequenceNumber);
/**
* Called when webrender is enabled, from the sampler thread. This function
diff --git a/gfx/layers/apz/src/APZUpdater.cpp b/gfx/layers/apz/src/APZUpdater.cpp
index 2bbad6e1a7..2f1b551f3a 100644
--- a/gfx/layers/apz/src/APZUpdater.cpp
+++ b/gfx/layers/apz/src/APZUpdater.cpp
@@ -191,14 +191,38 @@ void APZUpdater::UpdateScrollDataAndTreeState(
auto isFirstPaint = aScrollData.IsFirstPaint();
auto paintSequenceNumber = aScrollData.GetPaintSequenceNumber();
+ auto previous = self->mScrollData.find(aOriginatingLayersId);
+ // If there's the previous scroll data which hasn't yet been
+ // processed, we need to merge the previous scroll position updates
+ // into the latest one.
+ if (previous != self->mScrollData.end()) {
+ WebRenderScrollData& previousData = previous->second;
+ if (previousData.GetWasUpdateSkipped()) {
+ MOZ_ASSERT(previousData.IsFirstPaint());
+ aScrollData.PrependUpdates(previousData);
+ }
+ }
+
self->mScrollData[aOriginatingLayersId] = std::move(aScrollData);
auto root = self->mScrollData.find(aRootLayerTreeId);
if (root == self->mScrollData.end()) {
return;
}
- self->mApz->UpdateHitTestingTree(
- WebRenderScrollDataWrapper(*self, &(root->second)),
- isFirstPaint, aOriginatingLayersId, paintSequenceNumber);
+ if ((self->mApz->UpdateHitTestingTree(
+ WebRenderScrollDataWrapper(*self, &(root->second)),
+ isFirstPaint, aOriginatingLayersId, paintSequenceNumber) ==
+ APZCTreeManager::OriginatingLayersIdUpdated::No) &&
+ isFirstPaint) {
+ // If the given |aOriginatingLayersId| data wasn't used for
+ // updating, it's likly that the parent process hasn't yet
+ // received the LayersId as "ReferentId", thus we need to process
+ // it in a subsequent update where we got the "ReferentId".
+ //
+ // NOTE: We restrict the above previous scroll data prepending to
+ // the first paint case, otherwise the cumulative scroll data may
+ // be exploded if we have never received the "ReferenceId".
+ self->mScrollData[aOriginatingLayersId].SetWasUpdateSkipped();
+ }
}));
}
diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp
index 342375c019..edbd2ecffa 100644
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -106,6 +106,10 @@ static mozilla::LazyLogModule sApzCtlLog("apz.controller");
APZC_LOG("%p(%s scrollId=%" PRIu64 "): " fmt, (apzc), \
(apzc)->IsRootContent() ? "root" : "subframe", \
(apzc)->GetScrollId(), ##__VA_ARGS__)
+#define APZC_LOGV_DETAIL(fmt, apzc, ...) \
+ APZC_LOGV("%p(%s scrollId=%" PRIu64 "): " fmt, (apzc), \
+ (apzc)->IsRootContent() ? "root" : "subframe", \
+ (apzc)->GetScrollId(), ##__VA_ARGS__)
#define APZC_LOG_FM_COMMON(fm, prefix, level, ...) \
if (MOZ_LOG_TEST(sApzCtlLog, level)) { \
@@ -2248,6 +2252,11 @@ CSSRect AsyncPanZoomController::GetCurrentScrollRangeInCssPixels() const {
return Metrics().CalculateScrollRange();
}
+bool AsyncPanZoomController::AllowOneTouchPinch() const {
+ return StaticPrefs::apz_one_touch_pinch_enabled() &&
+ ZoomConstraintsAllowZoom();
+}
+
// Return whether or not the underlying layer can be scrolled on either axis.
bool AsyncPanZoomController::CanScroll(const InputData& aEvent) const {
ParentLayerPoint delta = GetDeltaForEvent(aEvent);
@@ -4734,7 +4743,7 @@ bool AsyncPanZoomController::UpdateAnimation(
// Even if there's no animation, if we have a scroll offset change pending due
// to the frame delay, we need to keep compositing.
if (mLastSampleTime == aSampleTime) {
- APZC_LOG_DETAIL(
+ APZC_LOGV_DETAIL(
"UpdateAnimation short-circuit, animation=%p, pending frame-delayed "
"offset=%d\n",
this, mAnimation.get(), HavePendingFrameDelayedOffset());
@@ -4754,8 +4763,8 @@ bool AsyncPanZoomController::UpdateAnimation(
// so that e.g. a main-thread animation can stay in sync with user-driven
// scrolling or a compositor animation.
bool needComposite = SampleCompositedAsyncTransform(aProofOfLock);
- APZC_LOG_DETAIL("UpdateAnimation needComposite=%d mAnimation=%p\n", this,
- needComposite, mAnimation.get());
+ APZC_LOGV_DETAIL("UpdateAnimation needComposite=%d mAnimation=%p\n", this,
+ needComposite, mAnimation.get());
TimeDuration sampleTimeDelta = aSampleTime - mLastSampleTime;
mLastSampleTime = aSampleTime;
@@ -5581,17 +5590,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(
aScrollMetadata.GetOverscrollBehavior());
}
- if (needToReclampScroll) {
- // Whenever scrollable rect or composition bounds has changed, we need to
- // re-clamp the scroll offset since it may be out of bounds. Also note that
- // we need to re-clamp before updating new scroll offsets from content since
- // we will use the last scroll offset to reflect the new offsets.
- ClampAndSetVisualScrollOffset(Metrics().GetVisualScrollOffset());
- for (auto& sampledState : mSampledState) {
- sampledState.ClampVisualScrollOffset(Metrics());
- }
- }
-
bool instantScrollMayTriggerTransform = false;
bool scrollOffsetUpdated = false;
bool smoothScrollRequested = false;
@@ -5738,20 +5736,11 @@ void AsyncPanZoomController::NotifyLayersUpdated(
relativeDelta =
Some(Metrics().ApplyPureRelativeScrollUpdateFrom(scrollUpdate));
Metrics().RecalculateLayoutViewportOffset();
- } else if (scrollUpdate.GetType() == ScrollUpdateType::MergeableAbsolute) {
- APZC_LOG("%p mergeable updating scroll offset from %s to %s\n", this,
- ToString(Metrics().GetVisualScrollOffset()).c_str(),
- ToString(scrollUpdate.GetDestination()).c_str());
- relativeDelta =
- Some(Metrics().ApplyAbsoluteScrollUpdateFrom(scrollUpdate).second);
- Metrics().RecalculateLayoutViewportOffset();
- scrollOffsetUpdated = true;
} else {
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
ToString(Metrics().GetVisualScrollOffset()).c_str(),
ToString(scrollUpdate.GetDestination()).c_str());
- auto [offsetChanged, _] =
- Metrics().ApplyAbsoluteScrollUpdateFrom(scrollUpdate);
+ bool offsetChanged = Metrics().ApplyScrollUpdateFrom(scrollUpdate);
Metrics().RecalculateLayoutViewportOffset();
if (offsetChanged || scrollUpdate.GetMode() != ScrollMode::Instant ||
@@ -5788,6 +5777,15 @@ void AsyncPanZoomController::NotifyLayersUpdated(
}
}
+ if (aIsFirstPaint || needToReclampScroll) {
+ // The scrollable rect or composition bounds may have changed in a way that
+ // makes our local scroll offset out of bounds, so clamp it.
+ ClampAndSetVisualScrollOffset(Metrics().GetVisualScrollOffset());
+ for (auto& sampledState : mSampledState) {
+ sampledState.ClampVisualScrollOffset(Metrics());
+ }
+ }
+
if (scrollOffsetUpdated) {
for (auto& sampledState : mSampledState) {
if (!didCancelAnimation && cumulativeRelativeDelta.isSome()) {
diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h
index fdc72b1971..d0c4537a66 100644
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -1305,6 +1305,8 @@ class AsyncPanZoomController {
*/
CSSRect GetCurrentScrollRangeInCssPixels() const;
+ bool AllowOneTouchPinch() const;
+
private:
/**
* Advances to the next sample, if there is one, the list of sampled states
diff --git a/gfx/layers/apz/src/AutoscrollAnimation.cpp b/gfx/layers/apz/src/AutoscrollAnimation.cpp
index 8d4b8fca10..45063ef2b4 100644
--- a/gfx/layers/apz/src/AutoscrollAnimation.cpp
+++ b/gfx/layers/apz/src/AutoscrollAnimation.cpp
@@ -17,7 +17,7 @@ namespace mozilla {
namespace layers {
// Helper function for AutoscrollAnimation::DoSample().
-// Basically copied as-is from toolkit/actors/AutoScrollChild.jsm.
+// Basically copied as-is from toolkit/actors/AutoScrollChild.sys.mjs.
static float Accelerate(ScreenCoord curr, ScreenCoord start) {
static const int speed = 12;
float val = (curr - start) / speed;
diff --git a/gfx/layers/apz/src/GenericScrollAnimation.cpp b/gfx/layers/apz/src/GenericScrollAnimation.cpp
index 04ca8c4697..62f19fab35 100644
--- a/gfx/layers/apz/src/GenericScrollAnimation.cpp
+++ b/gfx/layers/apz/src/GenericScrollAnimation.cpp
@@ -15,6 +15,9 @@
#include "ScrollAnimationMSDPhysics.h"
#include "mozilla/StaticPrefs_general.h"
+static mozilla::LazyLogModule sApzScrollAnimLog("apz.scrollanimation");
+#define GSA_LOG(...) MOZ_LOG(sApzScrollAnimLog, LogLevel::Debug, (__VA_ARGS__))
+
namespace mozilla {
namespace layers {
@@ -101,6 +104,12 @@ bool GenericScrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
// then end the animation early. Note that the initial displacement could be 0
// if the compositor ran very quickly (<1ms) after the animation was created.
// When that happens we want to make sure the animation continues.
+ GSA_LOG(
+ "Sampling GenericScrollAnimation: time %f finished %d sampledDest %s "
+ "adjustedOffset %s overscroll %s\n",
+ (now - TimeStamp::ProcessCreation()).ToMilliseconds(), finished,
+ ToString(CSSPoint::FromAppUnits(sampledDest)).c_str(),
+ ToString(adjustedOffset).c_str(), ToString(overscroll).c_str());
if (!IsZero(displacement / zoom) && IsZero(adjustedOffset / zoom)) {
// Nothing more to do - end the animation.
return false;
diff --git a/gfx/layers/apz/src/GestureEventListener.cpp b/gfx/layers/apz/src/GestureEventListener.cpp
index b54674b593..4300e9ba41 100644
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -5,13 +5,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GestureEventListener.h"
-#include <algorithm> // for max
+#include <algorithm> // for max
+#include <ostream>
#include <math.h> // for fabsf
#include <stddef.h> // for size_t
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
#include "InputBlockState.h" // for TouchBlockState
#include "base/task.h" // for CancelableTask, etc
#include "InputBlockState.h" // for TouchBlockState
+#include "mozilla/Assertions.h"
+#include "mozilla/EventForwards.h"
#include "mozilla/StaticPrefs_apz.h"
#include "mozilla/StaticPrefs_ui.h"
#include "nsDebug.h" // for NS_WARNING
@@ -83,8 +86,8 @@ GestureEventListener::~GestureEventListener() = default;
nsEventStatus GestureEventListener::HandleInputEvent(
const MultiTouchInput& aEvent) {
- GEL_LOG("Receiving event type %d with %zu touches in state %d\n",
- aEvent.mType, aEvent.mTouches.Length(), mState);
+ GEL_LOG("Receiving event type %d with %zu touches in state %s\n",
+ aEvent.mType, aEvent.mTouches.Length(), ToString(mState).c_str());
nsEventStatus rv = nsEventStatus_eIgnore;
@@ -175,16 +178,15 @@ nsEventStatus GestureEventListener::HandleInputTouchSingleStart() {
EnterFirstSingleTouchDown();
break;
case GESTURE_FIRST_SINGLE_TOUCH_UP:
+ // Bail out of any gesture that includes the first tap.
+ CancelLongTapTimeoutTask();
+ CancelMaxTapTimeoutTask();
if (SecondTapIsFar()) {
- // If the second tap goes down far away from the first, then bail out
- // of any gesture that includes the first tap.
- CancelLongTapTimeoutTask();
- CancelMaxTapTimeoutTask();
- mSingleTapSent = Nothing();
-
- // But still allow the second tap to participate in a gesture
+ // If the second tap goes down far away from the first,
+ // allow the second tap to participate in a gesture
// (e.g. lead to a single tap, or a double tap if an additional
// tap occurs near the same location).
+ mSingleTapSent = Nothing();
EnterFirstSingleTouchDown();
} else {
// Otherwise, reset the touch start position so that, if this turns into
@@ -225,9 +227,10 @@ nsEventStatus GestureEventListener::HandleInputTouchMultiStart() {
rv = nsEventStatus_eConsumeNoDefault;
break;
case GESTURE_FIRST_SINGLE_TOUCH_UP:
- case GESTURE_SECOND_SINGLE_TOUCH_DOWN:
// Cancel wait for double tap
CancelMaxTapTimeoutTask();
+ [[fallthrough]];
+ case GESTURE_SECOND_SINGLE_TOUCH_DOWN:
MOZ_ASSERT(mSingleTapSent.isSome());
if (!mSingleTapSent.value()) {
TriggerSingleTapConfirmedEvent();
@@ -307,12 +310,8 @@ nsEventStatus GestureEventListener::HandleInputTouchMove() {
// If touch has moved noticeably (within StaticPrefs::apz_max_tap_time()),
// change state.
if (MoveDistanceIsLarge()) {
- CancelLongTapTimeoutTask();
- CancelMaxTapTimeoutTask();
mSingleTapSent = Nothing();
- if (!StaticPrefs::apz_one_touch_pinch_enabled()) {
- // If the one-touch-pinch feature is disabled, bail out of the double-
- // tap gesture instead.
+ if (!mAsyncPanZoomController->AllowOneTouchPinch()) {
SetState(GESTURE_NONE);
break;
}
@@ -451,7 +450,6 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() {
}
case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
- CancelMaxTapTimeoutTask();
MOZ_ASSERT(mSingleTapSent.isSome());
mAsyncPanZoomController->HandleGestureEvent(CreateTapEvent(
mLastTouchInput, mSingleTapSent.value()
@@ -535,7 +533,9 @@ nsEventStatus GestureEventListener::HandleInputTouchCancel() {
}
void GestureEventListener::HandleInputTimeoutLongTap() {
- GEL_LOG("Running long-tap timeout task in state %d\n", mState);
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+ GEL_LOG("Running long-tap timeout task in state %s\n",
+ ToString(mState).c_str());
mLongTapTimeoutTask = nullptr;
@@ -559,14 +559,15 @@ void GestureEventListener::HandleInputTimeoutLongTap() {
}
void GestureEventListener::HandleInputTimeoutMaxTap(bool aDuringFastFling) {
- GEL_LOG("Running max-tap timeout task in state %d\n", mState);
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+ GEL_LOG("Running max-tap timeout task in state %s\n",
+ ToString(mState).c_str());
mMaxTapTimeoutTask = nullptr;
if (mState == GESTURE_FIRST_SINGLE_TOUCH_DOWN) {
SetState(GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN);
- } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP ||
- mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
+ } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP) {
MOZ_ASSERT(mSingleTapSent.isSome());
if (!aDuringFastFling && !mSingleTapSent.value()) {
TriggerSingleTapConfirmedEvent();
@@ -585,6 +586,8 @@ void GestureEventListener::TriggerSingleTapConfirmedEvent() {
}
void GestureEventListener::SetState(GestureState aState) {
+ GEL_LOG("State change from %s to %s", ToString(mState).c_str(),
+ ToString(aState).c_str());
mState = aState;
if (mState == GESTURE_NONE) {
@@ -598,10 +601,7 @@ void GestureEventListener::SetState(GestureState aState) {
}
void GestureEventListener::CancelLongTapTimeoutTask() {
- if (mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
- // being in this state means the task has been canceled already
- return;
- }
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
if (mLongTapTimeoutTask) {
mLongTapTimeoutTask->Cancel();
@@ -628,6 +628,8 @@ void GestureEventListener::CreateLongTapTimeoutTask() {
}
void GestureEventListener::CancelMaxTapTimeoutTask() {
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+
if (mState == GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN) {
// being in this state means the timer has just been triggered
return;
@@ -659,5 +661,40 @@ void GestureEventListener::CreateMaxTapTimeoutTask() {
std::max(0L, remainingDelay));
}
+std::ostream& operator<<(std::ostream& os,
+ GestureEventListener::GestureState aState) {
+ switch (aState) {
+ case GestureEventListener::GESTURE_NONE:
+ os << "GESTURE_NONE";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_DOWN:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_UP:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_UP";
+ break;
+ case GestureEventListener::GESTURE_SECOND_SINGLE_TOUCH_DOWN:
+ os << "GESTURE_SECOND_SINGLE_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_LONG_TOUCH_DOWN:
+ os << "GESTURE_LONG_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_MULTI_TOUCH_DOWN:
+ os << "GESTURE_MULTI_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_PINCH:
+ os << "GESTURE_PINCH";
+ break;
+ case GestureEventListener::GESTURE_ONE_TOUCH_PINCH:
+ os << "GESTURE_ONE_TOUCH_PINCH";
+ break;
+ }
+
+ return os;
+}
+
} // namespace layers
} // namespace mozilla
diff --git a/gfx/layers/apz/src/GestureEventListener.h b/gfx/layers/apz/src/GestureEventListener.h
index aa51889fdd..bf50d4f40a 100644
--- a/gfx/layers/apz/src/GestureEventListener.h
+++ b/gfx/layers/apz/src/GestureEventListener.h
@@ -7,6 +7,7 @@
#ifndef mozilla_layers_GestureEventListener_h
#define mozilla_layers_GestureEventListener_h
+#include <iosfwd>
#include "InputData.h" // for MultiTouchInput, etc
#include "Units.h"
#include "mozilla/EventForwards.h" // for nsEventStatus
@@ -135,6 +136,8 @@ class GestureEventListener final {
GESTURE_ONE_TOUCH_PINCH
};
+ friend std::ostream& operator<<(std::ostream& os, GestureState aState);
+
/**
* These HandleInput* functions comprise input alphabet of the GEL
* finite-state machine triggering state transitions.
diff --git a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
index f244ca4dc7..8256667d6b 100644
--- a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
+++ b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
@@ -21,12 +21,12 @@ class APZCGestureDetectorTester : public APZCBasicTester {
: APZCBasicTester(AsyncPanZoomController::USE_GESTURE_DETECTOR) {}
protected:
- FrameMetrics GetPinchableFrameMetrics() {
+ FrameMetrics GetPinchableFrameMetrics(float aZoom = 2.0f) {
FrameMetrics fm;
fm.SetCompositionBounds(ParentLayerRect(200, 200, 100, 200));
fm.SetScrollableRect(CSSRect(0, 0, 980, 1000));
fm.SetVisualScrollOffset(CSSPoint(300, 300));
- fm.SetZoom(CSSToParentLayerScale(2.0));
+ fm.SetZoom(CSSToParentLayerScale(aZoom));
// APZC only allows zooming on the root scrollable frame.
fm.SetIsRootContent(true);
// the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
@@ -843,3 +843,235 @@ TEST_F(APZCGestureDetectorTester, LongPressWithInputQueueDelay3) {
mcc->AdvanceByMillis(1);
check.Call("post long-tap dispatch");
}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureShort) {
+ // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
+ // hold second touch down for a very short time, then move
+ // and expect a successful one touch pinch gesture
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ MakeApzcZoomable();
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(10);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before beginning to move
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_NE(newZoom, oldZoom);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureLong) {
+ // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
+ // hold second touch down for a long time, then move
+ // and expect a successful one touch pinch gesture
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ MakeApzcZoomable();
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before beginning to move
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_NE(newZoom, oldZoom);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureNoMoveTriggersDoubleTap) {
+ // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
+ // then wait longer than StaticPrefs::apz_max_tap_time(), lift finger up
+ // and expect a successful double tap. No zooming should be performed
+ // by the one-touch pinch codepath.
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+
+ MakeApzcZoomable();
+
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
+ .Times(0);
+ EXPECT_CALL(*mcc,
+ HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _, _));
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before lifting the finger
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
+ TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_EQ(newZoom, oldZoom);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureNonZoomablePage) {
+ // Use a non-zoomable page. Perform a tap and a touch-drag
+ // which on a zoomable page trigger a one touch pinch gesture,
+ // and expect a single tap followed by a touch-scroll
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics(1.0f));
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ const auto oldScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
+ MakeApzcUnzoomable();
+
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
+ .Times(1);
+ EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _, _))
+ .Times(0);
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before beginning to move
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 100), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 100), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_EQ(newZoom, oldZoom);
+
+ const auto newScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
+ EXPECT_NE(newScrollOffset, oldScrollOffset);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureTimeout) {
+ // Take longer than StaticPrefs::apz_max_tap_time() until second touch down
+ // and expect no one touch pinch gesture being performed
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ MakeApzcZoomable();
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
+ .Times(1);
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time());
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_EQ(newZoom, oldZoom);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureDisabled) {
+ // With apz.one_touch_pinch disabled,
+ // perform one touch pinch gesture within the time threshold,
+ // and expect no zooming.
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", false);
+
+ MakeApzcZoomable();
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ const auto oldScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
+
+ // todo: enable following EXPECT_CALLs when fixing bug 1881794
+ // EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _,
+ // _))
+ // .Times(1);
+ // EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _,
+ // _))
+ // .Times(0);
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before beginning to move
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_EQ(newZoom, oldZoom);
+
+ const auto newScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
+ EXPECT_NE(newScrollOffset, oldScrollOffset);
+}
diff --git a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
index c290965845..1642bc147a 100644
--- a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
@@ -498,7 +498,7 @@ async function promiseNativeTouchpadPanEventAndWaitForObserver(
return new Promise(resolve => {
var observer = {
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
if (aTopic == "touchpadpanevent") {
resolve();
}
@@ -557,7 +557,7 @@ function promiseNativePanGestureEventAndWaitForObserver(
) {
return new Promise(resolve => {
var observer = {
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
if (aTopic == "mousescrollevent") {
resolve();
}
@@ -588,7 +588,7 @@ function promiseNativeWheelAndWaitForObserver(
) {
return new Promise(resolve => {
var observer = {
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
if (aTopic == "mousescrollevent") {
resolve();
}
@@ -614,7 +614,7 @@ function promiseNativeWheelAndWaitForWheelEvent(
var targetWindow = windowForTarget(aTarget);
targetWindow.addEventListener(
"wheel",
- function (e) {
+ function () {
setTimeout(resolve, 0);
},
{ once: true }
@@ -1566,7 +1566,7 @@ function promiseScrollend(aTarget = window) {
function promiseTouchEnd(element, count = 1) {
return new Promise(resolve => {
var eventCount = 0;
- var counterFunction = function (e) {
+ var counterFunction = function () {
eventCount++;
if (eventCount == count) {
element.removeEventListener("touchend", counterFunction, {
@@ -1816,7 +1816,7 @@ async function panRightToLeftUpdate(aElement, aX, aY, aMultiplier) {
);
}
-async function panRightToLeftEnd(aElement, aX, aY, aMultiplier) {
+async function panRightToLeftEnd(aElement, aX, aY) {
await NativePanHandler.promiseNativePanEvent(
aElement,
aX,
@@ -1869,7 +1869,7 @@ async function panLeftToRightUpdate(aElement, aX, aY, aMultiplier) {
);
}
-async function panLeftToRightEnd(aElement, aX, aY, aMultiplier) {
+async function panLeftToRightEnd(aElement, aX, aY) {
await NativePanHandler.promiseNativePanEvent(
aElement,
aX,
diff --git a/gfx/layers/apz/test/mochitest/apz_test_utils.js b/gfx/layers/apz/test/mochitest/apz_test_utils.js
index 821c66103d..cdae7824b2 100644
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -309,7 +309,7 @@ function promiseAfterPaint() {
// occurred by the the returned promise resolves. If you want to wait
// for those repaints, consider using promiseApzFlushedRepaints instead.
function promiseOnlyApzControllerFlushedWithoutSetTimeout(aWindow = window) {
- return new Promise(function (resolve, reject) {
+ return new Promise(function (resolve) {
var repaintDone = function () {
dump("PromiseApzRepaintsFlushed: APZ flush done\n");
SpecialPowers.Services.obs.removeObserver(
@@ -518,7 +518,7 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
if (test.onload) {
w.addEventListener(
"load",
- function (e) {
+ function () {
test.onload(w);
},
{ once: true }
diff --git a/gfx/layers/apz/test/mochitest/browser.toml b/gfx/layers/apz/test/mochitest/browser.toml
index 5432aa0ae1..67428eee23 100644
--- a/gfx/layers/apz/test/mochitest/browser.toml
+++ b/gfx/layers/apz/test/mochitest/browser.toml
@@ -19,7 +19,7 @@ support-files = ["helper_test_autoscrolling_in_oop_frame.html"]
support-files = ["helper_background_tab_load_scroll.html"]
["browser_test_background_tab_scroll.js"]
-skip-if = ["toolkit == 'android'"] # wheel events not supported on mobile
+skip-if = ["os == 'android'"] # wheel events not supported on mobile
support-files = ["helper_background_tab_scroll.html"]
["browser_test_content_response_timeout.js"]
@@ -28,7 +28,7 @@ support-files = ["helper_content_response_timeout.html"]
["browser_test_group_fission.js"]
skip-if = [
"win11_2009 && bits == 32", # intermittent failures on on win11/32
- "os == 'linux' && bits == 64", # Bug 1773830
+ "os == 'linux' && os_version == '18.04' && bits == 64", # Bug 1773830
]
support-files = [
"FissionTestHelperParent.sys.mjs",
@@ -49,7 +49,7 @@ support-files = ["helper_scroll_thumb_dragging.html"]
["browser_test_scrollbar_in_extension_popup_window.js"]
skip-if = [
"verify",
- "os == 'linux'" # Bug 1713052
+ "os == 'linux' && os_version == '18.04'" # Bug 1713052
]
["browser_test_scrolling_in_extension_popup_window.js"]
@@ -70,7 +70,7 @@ skip-if = ["os == 'win'"] # bug 1495580
support-files = ["helper_test_select_zoom.html"]
["browser_test_tab_drag_event_counts.js"]
-skip-if = ["os == 'linux'"] # No native key event support on Linux at this time (bug 1770143)
+skip-if = ["os == 'linux' && os_version == '18.04'"] # No native key event support on Linux at this time (bug 1770143)
support-files = [
"helper_test_tab_drag_event_counts.html"
]
diff --git a/gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js b/gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js
index 26d0ff6109..f7f83575f2 100644
--- a/gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js
+++ b/gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js
@@ -74,7 +74,7 @@ async function doTest() {
return new Promise(resolve => {
content.addEventListener(
"scroll",
- event => {
+ () => {
dump("Got a scroll event in the iframe\n");
resolve();
},
diff --git a/gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js b/gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js
index a80fd77c17..98f6ea6c29 100644
--- a/gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js
+++ b/gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js
@@ -60,6 +60,7 @@ add_task(async () => {
);
await new Promise(resolve => {
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
setTimeout(resolve, 200);
});
diff --git a/gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js b/gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js
index 6da3f3311b..9896e628e3 100644
--- a/gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js
+++ b/gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js
@@ -98,7 +98,7 @@ add_task(async () => {
return new Promise(resolve => {
content.window.addEventListener(
"scroll",
- event => {
+ () => {
dump("Got a scroll event in the popup content document\n");
resolve();
},
diff --git a/gfx/layers/apz/test/mochitest/helper_basic_scrollend.html b/gfx/layers/apz/test/mochitest/helper_basic_scrollend.html
index 9d71fe6251..6c31859690 100644
--- a/gfx/layers/apz/test/mochitest/helper_basic_scrollend.html
+++ b/gfx/layers/apz/test/mochitest/helper_basic_scrollend.html
@@ -19,7 +19,7 @@ const searchParams = new URLSearchParams(location.search);
async function test() {
var scrollendCount = 0;
- function onScrollend(e) {
+ function onScrollend() {
scrollendCount += 1;
}
diff --git a/gfx/layers/apz/test/mochitest/helper_browser_test_utils.js b/gfx/layers/apz/test/mochitest/helper_browser_test_utils.js
index ac68c9b1d4..22a072e48d 100644
--- a/gfx/layers/apz/test/mochitest/helper_browser_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/helper_browser_test_utils.js
@@ -4,7 +4,7 @@ Services.scriptloader.loadSubScript(
this
);
-function openSelectPopup(selector = "select", win = window) {
+function openSelectPopup(selector, win = window) {
let popupShownPromise = BrowserTestUtils.waitForSelectPopupShown(win);
EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true }, win);
return popupShownPromise;
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1346632.html b/gfx/layers/apz/test/mochitest/helper_bug1346632.html
index f91f8159b5..c7f92c3810 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1346632.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1346632.html
@@ -28,7 +28,7 @@
async function test() {
var root = document.scrollingElement;
var scrollPos = root.scrollTop;
- var scrollPromise = new Promise((resolve, reject) => {
+ var scrollPromise = new Promise((resolve) => {
document.addEventListener("scroll", () => {
ok(root.scrollTop > scrollPos, "document scrolled after dragging scrollbar");
resolve();
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1414336.html b/gfx/layers/apz/test/mochitest/helper_bug1414336.html
index 636328b7e4..c0d35db401 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1414336.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1414336.html
@@ -62,14 +62,14 @@ waitUntilApzStable().then(async () => {
let target0 = window.document.getElementById("target0");
let target0_events = ["pointerdown", "pointermove"];
- target0_events.forEach((elem, index, arr) => {
+ target0_events.forEach((elem) => {
target0.addEventListener(elem, (event) => {
is(event.type, target0_events[0], "receive " + event.type + " on target0");
target0_events.shift();
}, { once: true });
});
- target0.addEventListener("pointercancel", (event) => {
+ target0.addEventListener("pointercancel", () => {
ok(false, "Shouldn't receive pointercancel when content prevents default on touchstart");
// Wait until the event is done processing before we end the subtest,
// otherwise on Android the pointer events pref is flipped back to false
@@ -81,7 +81,7 @@ waitUntilApzStable().then(async () => {
event.preventDefault();
}, { once: true });
- target0.addEventListener("pointerup", (event) => {
+ target0.addEventListener("pointerup", () => {
ok(!target0_events.length, " should receive " + target0_events + " on target0");
// Wait until the event is done processing before we end the subtest,
// otherwise on Android the pointer events pref is flipped back to false
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html b/gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html
index 73badf4bc7..8534e8886b 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html
@@ -38,7 +38,7 @@
async function test() {
var target = document.getElementById("carousel");
- target.addEventListener("pointercancel", (event) => {
+ target.addEventListener("pointercancel", () => {
ok(false, "Received pointercancel, uh-oh!");
endEventReceived = true;
setTimeout(checkForTestEnd, 0);
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html b/gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html
index cc73fe99ea..b853bde04d 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html
@@ -11,7 +11,7 @@
<script type="application/javascript">
async function test() {
- document.getElementById("overlay").addEventListener("touchstart", function(e) {
+ document.getElementById("overlay").addEventListener("touchstart", function() {
// no need to do anything here. Just having a non-passive touchstart
// listener will force APZ to wait for the main thread to handle the
// touch event. The bug is that the touch-action:none property on the
@@ -34,7 +34,7 @@ async function test() {
// This promise will resolve after the main thread has processed
// all the synthesized touch events.
let promiseTouchEnd = new Promise(resolve => {
- var waitForTouchEnd = function(e) {
+ var waitForTouchEnd = function() {
dump("touchend listener hit\n");
resolve();
};
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1695598.html b/gfx/layers/apz/test/mochitest/helper_bug1695598.html
index fb6102e33d..7961d7ced4 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1695598.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1695598.html
@@ -19,7 +19,7 @@
let utils = SpecialPowers.getDOMWindowUtils(window);
let timeStamp = document.timeline.currentTime;
- async function sendScrollEvent(aRafTimestamp) {
+ async function sendScrollEvent() {
if (i < scrollEvents) {
if (timeStamp == document.timeline.currentTime) {
// If we are in a rAF callback at the same time stamp we've already
diff --git a/gfx/layers/apz/test/mochitest/helper_content_response_timeout.html b/gfx/layers/apz/test/mochitest/helper_content_response_timeout.html
index 41a0319699..c0481d01a4 100644
--- a/gfx/layers/apz/test/mochitest/helper_content_response_timeout.html
+++ b/gfx/layers/apz/test/mochitest/helper_content_response_timeout.html
@@ -11,7 +11,7 @@ div { height: 1000vh; }
</style>
<div id='target'></div>
<script>
-window.addEventListener('wheel', (e) => {
+window.addEventListener('wheel', () => {
const timeAtStart = window.performance.now();
while (window.performance.now() - timeAtStart < 200) {
// Make a 200ms busy state.
diff --git a/gfx/layers/apz/test/mochitest/helper_displayport_expiry.html b/gfx/layers/apz/test/mochitest/helper_displayport_expiry.html
index 023786a270..b463e4f39c 100644
--- a/gfx/layers/apz/test/mochitest/helper_displayport_expiry.html
+++ b/gfx/layers/apz/test/mochitest/helper_displayport_expiry.html
@@ -53,7 +53,7 @@ async function test() {
await promiseFrame();
let paintCount = 0;
- function countPaints(e) {
+ function countPaints() {
paintCount += 1;
}
diff --git a/gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html b/gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html
index 82f529bebd..8ebfc492f2 100644
--- a/gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html
+++ b/gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html
@@ -29,7 +29,7 @@ let code_for_oopif_to_run = function() {
let result = { x: e.clientX, y: e.clientY };
FissionTestHelper.fireEventInEmbedder("OOPIF:WheelData", result);
}, { passive: true });
- document.addEventListener("scroll", function(e) {
+ document.addEventListener("scroll", function() {
dump(`OOPIF got scroll to ${window.scrollX},${window.scrollY}\n`);
let result = { x: window.scrollX, y: window.scrollY };
FissionTestHelper.fireEventInEmbedder("OOPIF:Scrolled", result);
diff --git a/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html b/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html
index 2911b1eaf0..5a192c9f9e 100644
--- a/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html
+++ b/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html
@@ -66,7 +66,7 @@ let make_oopif_scrollable = function() {
FissionTestHelper.fireEventInEmbedder("OOPIF:Scrollable", result);
});
// Also register a scroll listener for when it actually gets scrolled.
- window.addEventListener("scroll", function(e) {
+ window.addEventListener("scroll", function() {
dump(`OOPIF got scroll event, now at ${window.scrollY}\n`);
let result = { y: window.scrollY };
FissionTestHelper.fireEventInEmbedder("OOPIF:Scrolled", result);
diff --git a/gfx/layers/apz/test/mochitest/helper_fullscreen.html b/gfx/layers/apz/test/mochitest/helper_fullscreen.html
index 32de4979f2..7ac443a1cc 100644
--- a/gfx/layers/apz/test/mochitest/helper_fullscreen.html
+++ b/gfx/layers/apz/test/mochitest/helper_fullscreen.html
@@ -27,7 +27,7 @@
});
}
- async function test(testDriver) {
+ async function test() {
target.requestFullscreen();
await waitForFullscreenChange();
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html b/gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html
index a04b1d3e83..30a9740d24 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html
@@ -38,7 +38,7 @@ for (var i = 3; i < 1000; i++) {
}
document.body.appendChild(div);
-async function test(testDriver) {
+async function test() {
var config = getHitTestConfig();
var utils = config.utils;
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html b/gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html
index 0f20719d46..b83b864aa2 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html
@@ -45,7 +45,7 @@ async function test() {
e.stopPropagation(); // do not propagate event to |fixed| ancestor
resolve();
});
- fixed.addEventListener("click", e => {
+ fixed.addEventListener("click", () => {
// Since target's listener calls stopPropagation(), if we get here
// then the coordinates of the click event did not correspond to
// |target|, but somewhere else on |fixed|.
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html b/gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html
index 2004ea9ae4..092c5b0dfa 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html
@@ -72,7 +72,7 @@ async function test() {
e.stopPropagation(); // do not propagate event to ancestors
resolve();
});
- fixed.addEventListener("click", e => {
+ fixed.addEventListener("click", () => {
// Since target's listener calls stopPropagation(), if we get here
// then the coordinates of the click event did not correspond to
// |target|, but somewhere else on |fixed|.
@@ -82,7 +82,7 @@ async function test() {
todo(false, "Fixed ancestor should not be hit");
resolve();
});
- window.addEventListener("click", e => {
+ window.addEventListener("click", () => {
// Similarly, the root content document's window should not be hit.
ok(false, "Root document should not be hit");
resolve();
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_fixed.html b/gfx/layers/apz/test/mochitest/helper_hittest_fixed.html
index 530c53fd7a..3185d83bf5 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_fixed.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_fixed.html
@@ -53,7 +53,7 @@ async function test() {
e.stopPropagation(); // do not propagate event to |fixed| ancestor
resolve();
});
- fixed.addEventListener("click", e => {
+ fixed.addEventListener("click", () => {
// Since target's listener calls stopPropagation(), if we get here
// then the coordinates of the click event did not correspond to
// |target|, but somewhere else on |fixed|.
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html b/gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html
index 0abed82156..6d9ea7bc53 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html
@@ -26,7 +26,7 @@
</body>
<script type="application/javascript">
-function test(testDriver) {
+function test() {
var config = getHitTestConfig();
var utils = config.utils;
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html b/gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html
index 9838a02aa9..b6128aaa87 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html
@@ -44,7 +44,7 @@ async function test() {
}
});
- window.addEventListener("mousedown", event => {
+ window.addEventListener("mousedown", () => {
ok(true, "Parent document should have received mouse-down");
resolve();
});
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html
index c245258b68..c33dff3f28 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html
@@ -63,7 +63,7 @@ function startListeningForClickEventsInChrome() {
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
}
let chromeReceivedClick = false;
- function chromeListener(e) {
+ function chromeListener() {
chromeReceivedClick = true;
}
topWin.addEventListener("click", chromeListener);
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html
index 8aff3103dd..0bb3972c8a 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html
@@ -43,7 +43,7 @@ function startListeningForContextmenuEventsInChrome() {
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
}
let chromeReceivedContextmenu = false;
- function chromeListener(e) {
+ function chromeListener() {
chromeReceivedContextmenu = true;
}
topWin.addEventListener("contextmenu", chromeListener);
@@ -95,7 +95,7 @@ async function test() {
let midGutter = 4 / deviceScale; // gutter is 8 *screen* pixels
startListeningForContextmenuEventsInChrome();
let contentReceivedContextmenu = false;
- let contentListener = function(e) {
+ let contentListener = function() {
contentReceivedContextmenu = true;
};
document.addEventListener("contextmenu", contentListener);
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html
index 36918b3682..ff97c34bd5 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html
@@ -84,7 +84,7 @@ async function test() {
// This makes sure we catch the case where the overscroll transform causes
// the event to incorrectly target the document.
let receivedClick = false;
- let listener = function(e) {
+ let listener = function() {
receivedClick = true;
};
document.addEventListener("click", listener);
diff --git a/gfx/layers/apz/test/mochitest/helper_key_scroll.html b/gfx/layers/apz/test/mochitest/helper_key_scroll.html
index 021e2803b7..4f574abd10 100644
--- a/gfx/layers/apz/test/mochitest/helper_key_scroll.html
+++ b/gfx/layers/apz/test/mochitest/helper_key_scroll.html
@@ -32,7 +32,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1383365
// page. This scroll is done synchronously because APZ doesn't have
// current focus state at page load.
let scrollBottomPromise = new Promise(resolve => {
- let checkBottom = function(e) {
+ let checkBottom = function() {
if (window.scrollY < window.scrollMaxY) {
return;
}
@@ -63,7 +63,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1383365
// This scroll should be asynchronous now that the focus state is up to date.
let scrollTopPromise = new Promise(resolve => {
- let checkTop = function(e) {
+ let checkTop = function() {
if (window.scrollY > 0) {
return;
}
diff --git a/gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html b/gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html
index 4f07db516e..c4a98ec7fa 100644
--- a/gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html
+++ b/gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html
@@ -25,7 +25,7 @@
async function test() {
let scrollendCount = 0;
- window.addEventListener("scrollend", e => {
+ window.addEventListener("scrollend", () => {
scrollendCount += 1;
});
diff --git a/gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html b/gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html
index 17ccb3a54d..9c98ecf727 100644
--- a/gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html
+++ b/gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html
@@ -22,7 +22,7 @@
<script type="application/javascript">
const utils = SpecialPowers.getDOMWindowUtils(window);
- async function test(testDriver) {
+ async function test() {
utils.scrollToVisual(100, 0, utils.UPDATE_TYPE_MAIN_THREAD,
utils.SCROLL_MODE_INSTANT);
diff --git a/gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html b/gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html
index 7280a26006..1c26fafdb7 100644
--- a/gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html
+++ b/gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html
@@ -22,7 +22,7 @@
<script type="application/javascript">
const utils = SpecialPowers.getDOMWindowUtils(window);
- async function test(testDriver) {
+ async function test() {
utils.scrollToVisual(100, 0, utils.UPDATE_TYPE_MAIN_THREAD,
utils.SCROLL_MODE_INSTANT);
diff --git a/gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html b/gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html
index 721ce7e538..755c4115e2 100644
--- a/gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html
+++ b/gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html
@@ -35,7 +35,7 @@ async function test() {
// trigger one scroll event, so a scroll event count of 1 indicates that a
// instant scroll was conducted.
let scrollCount = 0;
- window.addEventListener("scroll", (e) => {
+ window.addEventListener("scroll", () => {
scrollCount += 1;
});
diff --git a/gfx/layers/apz/test/mochitest/helper_touch_action_regions.html b/gfx/layers/apz/test/mochitest/helper_touch_action_regions.html
index 6a8a09e55a..14e800a561 100644
--- a/gfx/layers/apz/test/mochitest/helper_touch_action_regions.html
+++ b/gfx/layers/apz/test/mochitest/helper_touch_action_regions.html
@@ -293,7 +293,7 @@ function* test(testDriver) {
// waitUntilApzStable().then(runContinuation(myTest));
function runContinuation(testFunction) {
return function() {
- return new Promise(function(resolve, reject) {
+ return new Promise(function(resolve) {
var testContinuation = null;
function driveTest() {
diff --git a/gfx/layers/apz/test/mochitest/helper_zoomed_pan.html b/gfx/layers/apz/test/mochitest/helper_zoomed_pan.html
index 98547fb73f..0692c2f588 100644
--- a/gfx/layers/apz/test/mochitest/helper_zoomed_pan.html
+++ b/gfx/layers/apz/test/mochitest/helper_zoomed_pan.html
@@ -42,7 +42,7 @@
x: 0,
y: 0,
dx: (width) => -computeDelta(width),
- dy: (height) => 0,
+ dy: () => 0,
expected: {
x: [OFFSET_CSS_PX, "x-offset was adjusted"],
y: [0, "y-offset was not affected"],
@@ -51,7 +51,7 @@
{
x: OFFSET_CSS_PX,
y: 0,
- dx: (width) => 0,
+ dx: () => 0,
dy: (height) => -computeDelta(height),
expected: {
x: [OFFSET_CSS_PX, "x-offset was not affected"],
diff --git a/gfx/layers/apz/test/mochitest/test_smoothness.html b/gfx/layers/apz/test/mochitest/test_smoothness.html
index 64cb8bcefa..0f2ca3219e 100644
--- a/gfx/layers/apz/test/mochitest/test_smoothness.html
+++ b/gfx/layers/apz/test/mochitest/test_smoothness.html
@@ -23,7 +23,7 @@
SimpleTest.waitForExplicitFinish();
var utils = SpecialPowers.getDOMWindowUtils(window);
- async function sendScrollEvent(aRafTimestamp) {
+ async function sendScrollEvent() {
var scrollDiv = document.getElementById("content");
if (i < scrollEvents) {
diff --git a/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html b/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
index 71147d5238..0598f1a201 100644
--- a/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
+++ b/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
@@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1203140
const kResponseTimeoutMs = 2 * 60 * 1000; // 2 minutes
-function takeSnapshots(e) {
+function takeSnapshots() {
// Grab some snapshots, and make sure some of them are different (i.e. check
// the page is scrolling in the compositor, concurrently with this wheel
// listener running).
@@ -69,7 +69,7 @@ async function test() {
// Ensure the div is layerized by scrolling it
await promiseMoveMouseAndScrollWheelOver(box, 10, 10);
- box.addEventListener("touchstart", function(e) {
+ box.addEventListener("touchstart", function() {
ok(false, "This should never be run");
});
box.addEventListener("wheel", takeSnapshots, { capture: false, passive: true });
diff --git a/gfx/layers/apz/test/reftest/reftest.list b/gfx/layers/apz/test/reftest/reftest.list
index 77bfff3e6e..9af67384a8 100644
--- a/gfx/layers/apz/test/reftest/reftest.list
+++ b/gfx/layers/apz/test/reftest/reftest.list
@@ -1,14 +1,14 @@
# The following tests test the async positioning of the scrollbars.
# Basic root-frame scrollbar with async scrolling
# First make sure that we are actually drawing scrollbars
-skip-if(!asyncPan) pref(apz.allow_zooming,true) != async-scrollbar-1-v.html about:blank
-skip-if(!asyncPan) pref(apz.allow_zooming,true) != async-scrollbar-1-v-ref.html about:blank
-fuzzy-if(Android,0-5,0-6) fuzzy-if(gtkWidget,1-8,8-32) fuzzy-if(cocoaWidget,16-22,20-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
-fuzzy-if(Android,0-13,0-10) fuzzy-if(gtkWidget,1-30,4-32) fuzzy-if(cocoaWidget,14-22,20-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
-fuzzy-if(Android,0-13,0-21) fuzzy-if(gtkWidget,1-4,4-24) fuzzy-if(cocoaWidget,11-18,44-88) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
-fuzzy-if(Android,0-5,0-6) fuzzy-if(gtkWidget,1-8,8-32) fuzzy-if(cocoaWidget,16-22,20-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
-fuzzy-if(Android,0-14,0-10) fuzzy-if(gtkWidget,1-30,12-32) fuzzy-if(cocoaWidget,14-22,20-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
-fuzzy-if(Android,0-43,0-26) fuzzy-if(gtkWidget,0-14,12-32) fuzzy-if(cocoaWidget,11-18,26-76) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
+skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) != async-scrollbar-1-v.html about:blank
+skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) != async-scrollbar-1-v-ref.html about:blank
+fuzzy-if(Android,0-5,0-6) fuzzy-if(gtkWidget,1-8,8-32) fuzzy-if(cocoaWidget,16-22,20-44) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
+fuzzy-if(Android,0-13,0-10) fuzzy-if(gtkWidget,1-30,4-32) fuzzy-if(cocoaWidget,14-22,20-44) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
+fuzzy-if(Android,0-13,0-21) fuzzy-if(gtkWidget,1-4,4-24) fuzzy-if(cocoaWidget,11-18,44-88) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
+fuzzy-if(Android,0-5,0-6) fuzzy-if(gtkWidget,1-8,8-32) fuzzy-if(cocoaWidget,16-22,20-44) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
+fuzzy-if(Android,0-14,0-10) fuzzy-if(gtkWidget,1-30,12-32) fuzzy-if(cocoaWidget,14-22,20-44) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
+fuzzy-if(Android,0-43,0-26) fuzzy-if(gtkWidget,0-14,12-32) fuzzy-if(cocoaWidget,11-18,26-76) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
# Different async zoom levels. Since the scrollthumb gets async-scaled in the
# compositor, the border-radius ends of the scrollthumb are going to be a little
@@ -37,7 +37,7 @@ fuzzy-if(Android,0-28,0-23) fuzzy-if(!Android,0-107,0-34) pref(apz.allow_zooming
# Meta-viewport tag support
skip-if(!Android) pref(apz.allow_zooming,true) == initial-scale-1.html initial-scale-1-ref.html
-skip-if(!asyncPan) == frame-reconstruction-scroll-clamping.html frame-reconstruction-scroll-clamping-ref.html
+skip-if(useDrawSnapshot) == frame-reconstruction-scroll-clamping.html frame-reconstruction-scroll-clamping-ref.html
# Test that position:fixed and position:sticky elements are attached to the
# layout viewport.
diff --git a/gfx/layers/apz/testutil/APZTestData.h b/gfx/layers/apz/testutil/APZTestData.h
index e4a73c80cc..d180bbcf1d 100644
--- a/gfx/layers/apz/testutil/APZTestData.h
+++ b/gfx/layers/apz/testutil/APZTestData.h
@@ -144,10 +144,10 @@ class APZTestData {
// A helper class for logging data for a paint.
class APZPaintLogHelper {
public:
- APZPaintLogHelper(APZTestData* aTestData, SequenceNumber aPaintSequenceNumber)
+ APZPaintLogHelper(APZTestData* aTestData, SequenceNumber aPaintSequenceNumber,
+ bool aIsTestLoggingEnabled)
: mTestData(aTestData), mPaintSequenceNumber(aPaintSequenceNumber) {
- MOZ_ASSERT(!aTestData || StaticPrefs::apz_test_logging_enabled(),
- "don't call me");
+ MOZ_ASSERT(!aTestData || aIsTestLoggingEnabled, "don't call me");
}
template <typename Value>
diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp
index 9ad65ce981..508cd8e67f 100644
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -518,7 +518,8 @@ nsEventStatus APZCCallbackHelper::DispatchSynthesizedMouseEvent(
WidgetMouseEvent::eNormal);
event.mRefPoint = LayoutDeviceIntPoint::Truncate(aRefPoint.x, aRefPoint.y);
event.mButton = MouseButton::ePrimary;
- event.mButtons |= MouseButtonsFlag::ePrimaryFlag;
+ event.mButtons = aMsg == eMouseDown ? MouseButtonsFlag::ePrimaryFlag
+ : MouseButtonsFlag::eNoButtons;
event.mInputSource = dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH;
if (aMsg == eMouseLongTap) {
event.mFlags.mOnlyChromeDispatch = true;
diff --git a/gfx/layers/apz/util/APZEventState.cpp b/gfx/layers/apz/util/APZEventState.cpp
index 7384296f45..5db6a08429 100644
--- a/gfx/layers/apz/util/APZEventState.cpp
+++ b/gfx/layers/apz/util/APZEventState.cpp
@@ -240,7 +240,7 @@ void APZEventState::ProcessLongTap(PresShell* aPresShell,
false;
#elif defined(MOZ_WIDGET_ANDROID)
// On Android, GeckoView calls preventDefault() in a JSActor
- // (ContentDelegateChild.jsm) when opening context menu so that we can
+ // (ContentDelegateChild.sys.mjs) when opening context menu so that we can
// tell whether contextmenu opens in response to the contextmenu event by
// checking where preventDefault() got called.
preventDefaultResult == PreventDefaultResult::ByChrome;
diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp
index bfc20b9b08..4187e48955 100644
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -27,6 +27,7 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/ipc/CrossProcessSemaphore.h"
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
+#include "mozilla/layers/CanvasRenderer.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/ImageBridgeChild.h"
@@ -375,7 +376,8 @@ TextureData* TextureData::Create(TextureForwarder* aAllocator,
RefPtr<CanvasChild> canvasChild = aAllocator->GetCanvasChild();
if (canvasChild) {
return new RecordedTextureData(canvasChild.forget(), aSize, aFormat,
- textureType);
+ textureType,
+ layers::TexTypeForWebgl(aKnowsCompositor));
}
// If we must be remote, but there is no canvas child, then falling back
// is not possible.
@@ -746,12 +748,10 @@ void TextureClient::ReadUnlock() {
}
bool TextureClient::Lock(OpenMode aMode) {
- MOZ_ASSERT(IsValid());
- MOZ_ASSERT(!mIsLocked);
- if (!IsValid()) {
+ if (NS_WARN_IF(!IsValid())) {
return false;
}
- if (mIsLocked) {
+ if (NS_WARN_IF(mIsLocked)) {
return mOpenMode == aMode;
}
diff --git a/gfx/layers/client/TextureRecorded.cpp b/gfx/layers/client/TextureRecorded.cpp
index 7e7ee2da99..da4ca4f8f3 100644
--- a/gfx/layers/client/TextureRecorded.cpp
+++ b/gfx/layers/client/TextureRecorded.cpp
@@ -23,9 +23,10 @@ static int64_t sNextRecordedTextureId = 0;
RecordedTextureData::RecordedTextureData(
already_AddRefed<CanvasChild> aCanvasChild, gfx::IntSize aSize,
- gfx::SurfaceFormat aFormat, TextureType aTextureType)
+ gfx::SurfaceFormat aFormat, TextureType aTextureType,
+ TextureType aWebglTextureType)
: mCanvasChild(aCanvasChild), mSize(aSize), mFormat(aFormat) {
- mCanvasChild->EnsureRecorder(aSize, aFormat, aTextureType);
+ mCanvasChild->EnsureRecorder(aSize, aFormat, aTextureType, aWebglTextureType);
}
RecordedTextureData::~RecordedTextureData() {
diff --git a/gfx/layers/client/TextureRecorded.h b/gfx/layers/client/TextureRecorded.h
index d846c1fac1..56e504fb54 100644
--- a/gfx/layers/client/TextureRecorded.h
+++ b/gfx/layers/client/TextureRecorded.h
@@ -18,7 +18,8 @@ class RecordedTextureData final : public TextureData {
public:
RecordedTextureData(already_AddRefed<CanvasChild> aCanvasChild,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
- TextureType aTextureType);
+ TextureType aTextureType,
+ TextureType aWebglTextureType = TextureType::Unknown);
void FillInfo(TextureData::Info& aInfo) const final;
diff --git a/gfx/layers/ipc/CanvasChild.cpp b/gfx/layers/ipc/CanvasChild.cpp
index 553217d82b..515463cd8e 100644
--- a/gfx/layers/ipc/CanvasChild.cpp
+++ b/gfx/layers/ipc/CanvasChild.cpp
@@ -7,6 +7,9 @@
#include "CanvasChild.h"
#include "MainThreadUtils.h"
+#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/WorkerRef.h"
+#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/gfx/CanvasManagerChild.h"
#include "mozilla/gfx/DrawTargetRecording.h"
#include "mozilla/gfx/Tools.h"
@@ -18,6 +21,7 @@
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/SourceSurfaceSharedData.h"
#include "mozilla/Maybe.h"
+#include "mozilla/Mutex.h"
#include "nsIObserverService.h"
#include "RecordedCanvasEventImpl.h"
@@ -33,9 +37,9 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers {
~RecorderHelpers() override = default;
- bool InitTranslator(TextureType aTextureType, gfx::BackendType aBackendType,
- Handle&& aReadHandle, nsTArray<Handle>&& aBufferHandles,
- uint64_t aBufferSize,
+ bool InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
+ gfx::BackendType aBackendType, Handle&& aReadHandle,
+ nsTArray<Handle>&& aBufferHandles, uint64_t aBufferSize,
CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) override {
NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
@@ -43,7 +47,7 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers {
return false;
}
return mCanvasChild->SendInitTranslator(
- aTextureType, aBackendType, std::move(aReadHandle),
+ aTextureType, aWebglTextureType, aBackendType, std::move(aReadHandle),
std::move(aBufferHandles), aBufferSize, std::move(aReaderSem),
std::move(aWriterSem));
}
@@ -165,9 +169,104 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
bool mDetached = false;
};
-CanvasChild::CanvasChild() = default;
+class CanvasDataShmemHolder {
+ public:
+ CanvasDataShmemHolder(ipc::SharedMemoryBasic* aShmem,
+ CanvasChild* aCanvasChild)
+ : mMutex("CanvasChild::DataShmemHolder::mMutex"),
+ mShmem(aShmem),
+ mCanvasChild(aCanvasChild) {}
+
+ bool Init(dom::ThreadSafeWorkerRef* aWorkerRef) {
+ if (!aWorkerRef) {
+ return true;
+ }
-CanvasChild::~CanvasChild() = default;
+ RefPtr<dom::StrongWorkerRef> workerRef = dom::StrongWorkerRef::Create(
+ aWorkerRef->Private(), "CanvasChild::DataShmemHolder",
+ [this]() { DestroyWorker(); });
+ if (NS_WARN_IF(!workerRef)) {
+ return false;
+ }
+
+ MutexAutoLock lock(mMutex);
+ mWorkerRef = new dom::ThreadSafeWorkerRef(workerRef);
+ return true;
+ }
+
+ void Destroy() {
+ class DestroyRunnable final : public dom::WorkerRunnable {
+ public:
+ DestroyRunnable(dom::WorkerPrivate* aWorkerPrivate,
+ CanvasDataShmemHolder* aShmemHolder)
+ : dom::WorkerRunnable(aWorkerPrivate,
+ "CanvasDataShmemHolder::Destroy",
+ dom::WorkerRunnable::WorkerThread),
+ mShmemHolder(aShmemHolder) {}
+
+ bool WorkerRun(JSContext* aCx,
+ dom::WorkerPrivate* aWorkerPrivate) override {
+ mShmemHolder->Destroy();
+ return true;
+ }
+
+ void PostRun(JSContext* aCx, dom::WorkerPrivate* aWorkerPrivate,
+ bool aRunResult) override {}
+
+ bool PreDispatch(dom::WorkerPrivate* aWorkerPrivate) override {
+ return true;
+ }
+
+ void PostDispatch(dom::WorkerPrivate* aWorkerPrivate,
+ bool aDispatchResult) override {}
+
+ private:
+ CanvasDataShmemHolder* mShmemHolder;
+ };
+
+ mMutex.Lock();
+
+ if (mCanvasChild) {
+ if (mWorkerRef) {
+ if (!mWorkerRef->Private()->IsOnCurrentThread()) {
+ auto task = MakeRefPtr<DestroyRunnable>(mWorkerRef->Private(), this);
+ mMutex.Unlock();
+ task->Dispatch();
+ return;
+ }
+ } else if (!NS_IsMainThread()) {
+ mMutex.Unlock();
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "CanvasDataShmemHolder::Destroy", [this]() { Destroy(); }));
+ return;
+ }
+
+ mCanvasChild->ReturnDataSurfaceShmem(mShmem.forget());
+ mCanvasChild = nullptr;
+ mWorkerRef = nullptr;
+ }
+
+ mMutex.Unlock();
+ delete this;
+ }
+
+ void DestroyWorker() {
+ MutexAutoLock lock(mMutex);
+ mCanvasChild = nullptr;
+ mWorkerRef = nullptr;
+ }
+
+ private:
+ Mutex mMutex;
+ RefPtr<ipc::SharedMemoryBasic> mShmem;
+ RefPtr<CanvasChild> mCanvasChild MOZ_GUARDED_BY(mMutex);
+ RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef MOZ_GUARDED_BY(mMutex);
+};
+
+CanvasChild::CanvasChild(dom::ThreadSafeWorkerRef* aWorkerRef)
+ : mWorkerRef(aWorkerRef) {}
+
+CanvasChild::~CanvasChild() { MOZ_ASSERT(!mWorkerRef); }
static void NotifyCanvasDeviceReset() {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@@ -207,14 +306,15 @@ ipc::IPCResult CanvasChild::RecvBlockCanvas() {
}
void CanvasChild::EnsureRecorder(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
- TextureType aTextureType) {
+ TextureType aTextureType,
+ TextureType aWebglTextureType) {
NS_ASSERT_OWNINGTHREAD(CanvasChild);
if (!mRecorder) {
gfx::BackendType backendType =
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
- auto recorder = MakeRefPtr<CanvasDrawEventRecorder>();
- if (!recorder->Init(aTextureType, backendType,
+ auto recorder = MakeRefPtr<CanvasDrawEventRecorder>(mWorkerRef);
+ if (!recorder->Init(aTextureType, aWebglTextureType, backendType,
MakeUnique<RecorderHelpers>(this))) {
return;
}
@@ -242,6 +342,8 @@ void CanvasChild::Destroy() {
if (CanSend()) {
Send__delete__(this);
}
+
+ mWorkerRef = nullptr;
}
bool CanvasChild::EnsureBeginTransaction() {
@@ -397,6 +499,10 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
return nullptr;
}
+ gfx::IntSize ssSize = aSurface->GetSize();
+ gfx::SurfaceFormat ssFormat = aSurface->GetFormat();
+ auto stride = ImageDataSerializer::ComputeRGBStride(ssFormat, ssSize.width);
+
// Shmem is only valid if the surface is the latest snapshot (not detached).
if (!aDetached) {
// If there is a shmem associated with this snapshot id, then we want to try
@@ -411,20 +517,22 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
if (NS_WARN_IF(!mRecorder->WaitForCheckpoint(checkpoint))) {
return nullptr;
}
- gfx::IntSize size = aSurface->GetSize();
- gfx::SurfaceFormat format = aSurface->GetFormat();
- auto stride = ImageDataSerializer::ComputeRGBStride(format, size.width);
+ auto* closure =
+ new CanvasDataShmemHolder(it->second.mSnapshotShmem, this);
+ if (NS_WARN_IF(!closure->Init(mWorkerRef))) {
+ delete closure;
+ return nullptr;
+ }
RefPtr<gfx::DataSourceSurface> dataSurface =
- gfx::Factory::CreateWrappingDataSourceSurface(shmemPtr, stride, size,
- format);
+ gfx::Factory::CreateWrappingDataSourceSurface(
+ shmemPtr, stride, ssSize, ssFormat, ReleaseDataShmemHolder,
+ closure);
return dataSurface.forget();
}
}
RecordEvent(RecordedPrepareDataForSurface(aSurface));
- gfx::IntSize ssSize = aSurface->GetSize();
- gfx::SurfaceFormat ssFormat = aSurface->GetFormat();
if (!EnsureDataSurfaceShmem(ssSize, ssFormat)) {
return nullptr;
}
@@ -435,15 +543,15 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
return nullptr;
}
+ auto* closure = new CanvasDataShmemHolder(mDataSurfaceShmem, this);
+ if (NS_WARN_IF(!closure->Init(mWorkerRef))) {
+ delete closure;
+ return nullptr;
+ }
+
mDataSurfaceShmemAvailable = false;
- struct DataShmemHolder {
- RefPtr<ipc::SharedMemoryBasic> shmem;
- RefPtr<CanvasChild> canvasChild;
- };
auto* data = static_cast<uint8_t*>(mDataSurfaceShmem->memory());
- auto* closure = new DataShmemHolder{do_AddRef(mDataSurfaceShmem), this};
- auto stride = ImageDataSerializer::ComputeRGBStride(ssFormat, ssSize.width);
RefPtr<gfx::DataSourceSurface> dataSurface =
gfx::Factory::CreateWrappingDataSourceSurface(
@@ -452,16 +560,8 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
}
/* static */ void CanvasChild::ReleaseDataShmemHolder(void* aClosure) {
- if (!NS_IsMainThread()) {
- NS_DispatchToMainThread(NS_NewRunnableFunction(
- "CanvasChild::ReleaseDataShmemHolder",
- [aClosure]() { ReleaseDataShmemHolder(aClosure); }));
- return;
- }
-
- auto* shmemHolder = static_cast<DataShmemHolder*>(aClosure);
- shmemHolder->canvasChild->ReturnDataSurfaceShmem(shmemHolder->shmem.forget());
- delete shmemHolder;
+ auto* shmemHolder = static_cast<CanvasDataShmemHolder*>(aClosure);
+ shmemHolder->Destroy();
}
already_AddRefed<gfx::SourceSurface> CanvasChild::WrapSurface(
diff --git a/gfx/layers/ipc/CanvasChild.h b/gfx/layers/ipc/CanvasChild.h
index c99fe50bfb..e22109f406 100644
--- a/gfx/layers/ipc/CanvasChild.h
+++ b/gfx/layers/ipc/CanvasChild.h
@@ -15,6 +15,10 @@
namespace mozilla {
+namespace dom {
+class ThreadSafeWorkerRef;
+}
+
namespace gfx {
class DrawTargetRecording;
class SourceSurface;
@@ -28,7 +32,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
public:
NS_INLINE_DECL_REFCOUNTING(CanvasChild)
- CanvasChild();
+ explicit CanvasChild(dom::ThreadSafeWorkerRef* aWorkerRef);
/**
* @returns true if remote canvas has been deactivated due to failure.
@@ -58,7 +62,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
* @params aTextureType the TextureType to create in the CanvasTranslator.
*/
void EnsureRecorder(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
- TextureType aTextureType);
+ TextureType aTextureType, TextureType aWebglTextureType);
/**
* Clean up IPDL actor.
@@ -147,6 +151,9 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
void CleanupTexture(int64_t aTextureId);
+ void ReturnDataSurfaceShmem(
+ already_AddRefed<ipc::SharedMemoryBasic> aDataSurfaceShmem);
+
protected:
void ActorDestroy(ActorDestroyReason aWhy) final;
@@ -157,14 +164,6 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
bool EnsureDataSurfaceShmem(gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
- void ReturnDataSurfaceShmem(
- already_AddRefed<ipc::SharedMemoryBasic> aDataSurfaceShmem);
-
- struct DataShmemHolder {
- RefPtr<ipc::SharedMemoryBasic> shmem;
- RefPtr<CanvasChild> canvasChild;
- };
-
static void ReleaseDataShmemHolder(void* aClosure);
void DropFreeBuffersWhenDormant();
@@ -173,6 +172,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
static bool mDeactivated;
+ RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
RefPtr<CanvasDrawEventRecorder> mRecorder;
RefPtr<ipc::SharedMemoryBasic> mDataSurfaceShmem;
diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp
index 08150d6952..4a184f48d8 100644
--- a/gfx/layers/ipc/CanvasTranslator.cpp
+++ b/gfx/layers/ipc/CanvasTranslator.cpp
@@ -13,6 +13,7 @@
#include "mozilla/gfx/DrawTargetWebgl.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUParent.h"
+#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/layers/BufferTexture.h"
@@ -131,15 +132,17 @@ bool CanvasTranslator::EnsureSharedContextWebgl() {
}
mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
- TextureType aTextureType, gfx::BackendType aBackendType,
- Handle&& aReadHandle, nsTArray<Handle>&& aBufferHandles,
- uint64_t aBufferSize, CrossProcessSemaphoreHandle&& aReaderSem,
+ TextureType aTextureType, TextureType aWebglTextureType,
+ gfx::BackendType aBackendType, Handle&& aReadHandle,
+ nsTArray<Handle>&& aBufferHandles, uint64_t aBufferSize,
+ CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) {
if (mHeaderShmem) {
return IPC_FAIL(this, "RecvInitTranslator called twice.");
}
mTextureType = aTextureType;
+ mWebglTextureType = aWebglTextureType;
mBackendType = aBackendType;
mOtherPid = OtherPid();
@@ -637,7 +640,11 @@ bool CanvasTranslator::HandleExtensionEvent(int32_t aType) {
}
}
-void CanvasTranslator::BeginTransaction() { mIsInTransaction = true; }
+void CanvasTranslator::BeginTransaction() {
+ PROFILER_MARKER_TEXT("CanvasTranslator", GRAPHICS, {},
+ "CanvasTranslator::BeginTransaction"_ns);
+ mIsInTransaction = true;
+}
void CanvasTranslator::Flush() {
#if defined(XP_WIN)
@@ -728,9 +735,15 @@ bool CanvasTranslator::CheckForFreshCanvasDevice(int aLineNumber) {
NotifyDeviceChanged();
}
- RefPtr<Runnable> runnable = NS_NewRunnableFunction(
- "CanvasTranslator NotifyDeviceReset",
- []() { gfx::GPUParent::GetSingleton()->NotifyDeviceReset(); });
+ RefPtr<Runnable> runnable =
+ NS_NewRunnableFunction("CanvasTranslator NotifyDeviceReset", []() {
+ if (XRE_IsGPUProcess()) {
+ gfx::GPUParent::GetSingleton()->NotifyDeviceReset();
+ } else {
+ gfx::GPUProcessManager::Get()->OnInProcessDeviceReset(
+ /* aTrackThreshold */ false);
+ }
+ });
// It is safe to wait here because only the Compositor thread waits on us and
// the main thread doesn't wait on the compositor thread in the GPU process.
@@ -1025,6 +1038,8 @@ bool CanvasTranslator::UnlockTexture(int64_t aTextureId) {
}
bool CanvasTranslator::PresentTexture(int64_t aTextureId, RemoteTextureId aId) {
+ AUTO_PROFILER_MARKER_TEXT("CanvasTranslator", GRAPHICS, {},
+ "CanvasTranslator::PresentTexture"_ns);
auto result = mTextureInfo.find(aTextureId);
if (result == mTextureInfo.end()) {
return false;
@@ -1033,7 +1048,8 @@ bool CanvasTranslator::PresentTexture(int64_t aTextureId, RemoteTextureId aId) {
RemoteTextureOwnerId ownerId = info.mRemoteTextureOwnerId;
if (gfx::DrawTargetWebgl* webgl = info.GetDrawTargetWebgl()) {
EnsureRemoteTextureOwner(ownerId);
- if (webgl->CopyToSwapChain(aId, ownerId, mRemoteTextureOwner)) {
+ if (webgl->CopyToSwapChain(mWebglTextureType, aId, ownerId,
+ mRemoteTextureOwner)) {
return true;
}
if (mSharedContext && mSharedContext->IsContextLost()) {
diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h
index cf87b7ab53..5258e0c529 100644
--- a/gfx/layers/ipc/CanvasTranslator.h
+++ b/gfx/layers/ipc/CanvasTranslator.h
@@ -69,6 +69,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
* CanvasEventRingBuffer.
*
* @param aTextureType the TextureType the translator will create
+ * @param aWebglTextureType the TextureType of any WebGL buffers
* @param aBackendType the BackendType for texture data
* @param aHeaderHandle handle for the control header
* @param aBufferHandles handles for the initial buffers for translation
@@ -77,6 +78,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
* @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
*/
ipc::IPCResult RecvInitTranslator(TextureType aTextureType,
+ TextureType aWebglTextureType,
gfx::BackendType aBackendType,
Handle&& aReadHandle,
nsTArray<Handle>&& aBufferHandles,
@@ -358,6 +360,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
TextureType mTextureType = TextureType::Unknown;
+ TextureType mWebglTextureType = TextureType::Unknown;
UniquePtr<TextureData> mReferenceTextureData;
dom::ContentParentId mContentId;
uint32_t mManagerId;
diff --git a/gfx/layers/ipc/CompositorManagerChild.cpp b/gfx/layers/ipc/CompositorManagerChild.cpp
index 0e553745d3..8d89339373 100644
--- a/gfx/layers/ipc/CompositorManagerChild.cpp
+++ b/gfx/layers/ipc/CompositorManagerChild.cpp
@@ -10,6 +10,7 @@
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/CompositorManagerParent.h"
#include "mozilla/layers/CompositorThread.h"
+#include "mozilla/gfx/CanvasShutdownManager.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/dom/ContentChild.h" // for ContentChild
@@ -67,7 +68,15 @@ bool CompositorManagerChild::Init(Endpoint<PCompositorManagerChild>&& aEndpoint,
sInstance = new CompositorManagerChild(std::move(aEndpoint), aProcessToken,
aNamespace);
sOtherPid = sInstance->OtherPid();
- return sInstance->CanSend();
+ if (!sInstance->CanSend()) {
+ return false;
+ }
+
+ // If there are any canvases waiting on the recreation of the GPUProcess or
+ // CompositorManagerChild, then we need to notify them so that they can
+ // restore their contexts.
+ gfx::CanvasShutdownManager::OnCompositorManagerRestored();
+ return true;
}
/* static */
diff --git a/gfx/layers/ipc/LayersMessageUtils.h b/gfx/layers/ipc/LayersMessageUtils.h
index d869d4ed83..a4e9557ac3 100644
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -520,7 +520,7 @@ template <>
struct ParamTraits<mozilla::ScrollUpdateType>
: public ContiguousEnumSerializerInclusive<
mozilla::ScrollUpdateType, mozilla::ScrollUpdateType::Absolute,
- mozilla::ScrollUpdateType::MergeableAbsolute> {};
+ mozilla::ScrollUpdateType::PureRelative> {};
template <>
struct ParamTraits<mozilla::ScrollMode>
diff --git a/gfx/layers/ipc/PCanvas.ipdl b/gfx/layers/ipc/PCanvas.ipdl
index 5187e61d23..59896b72cf 100644
--- a/gfx/layers/ipc/PCanvas.ipdl
+++ b/gfx/layers/ipc/PCanvas.ipdl
@@ -32,9 +32,9 @@ parent:
* each aBufferHandles' memory and the default size. aReaderSem and aWriterSem
* are handles for the semaphores to handle waiting on either side.
*/
- async InitTranslator(TextureType aTextureType, BackendType aBackendType,
- Handle aHeaderHandle, Handle[] aBufferHandles,
- uint64_t aBufferSize,
+ async InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
+ BackendType aBackendType, Handle aHeaderHandle,
+ Handle[] aBufferHandles, uint64_t aBufferSize,
CrossProcessSemaphoreHandle aReaderSem,
CrossProcessSemaphoreHandle aWriterSem);
diff --git a/gfx/layers/ipc/VideoBridgeParent.cpp b/gfx/layers/ipc/VideoBridgeParent.cpp
index 6413c27bc1..50f0549e50 100644
--- a/gfx/layers/ipc/VideoBridgeParent.cpp
+++ b/gfx/layers/ipc/VideoBridgeParent.cpp
@@ -17,9 +17,8 @@ namespace mozilla::layers {
using namespace mozilla::ipc;
using namespace mozilla::gfx;
-using VideoBridgeTable =
- EnumeratedArray<VideoBridgeSource, VideoBridgeSource::_Count,
- VideoBridgeParent*>;
+using VideoBridgeTable = EnumeratedArray<VideoBridgeSource, VideoBridgeParent*,
+ size_t(VideoBridgeSource::_Count)>;
static StaticDataMutex<VideoBridgeTable> sVideoBridgeFromProcess(
"VideoBridges");
diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build
index 1bf2e83804..384611b68b 100644
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -260,7 +260,7 @@ if CONFIG["MOZ_WAYLAND"]:
"SurfacePoolWayland.cpp",
]
-if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
EXPORTS.mozilla.layers += [
"NativeLayerCA.h",
"SurfacePoolCA.h",
@@ -458,7 +458,7 @@ DEFINES["GOOGLE_PROTOBUF_NO_RTTI"] = True
DEFINES["GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER"] = True
DEFINES["MOZ_APP_VERSION"] = CONFIG["MOZ_APP_VERSION"]
-if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
SOURCES += [
"opengl/MacIOSurfaceTextureClientOGL.cpp",
"opengl/MacIOSurfaceTextureHostOGL.cpp",
diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
index ee61045599..112ed7711c 100644
--- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
@@ -10,7 +10,6 @@
#include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/webrender/WebRenderAPI.h"
-#include "GLContextCGL.h"
namespace mozilla {
namespace layers {
diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp
index 464b8fb69f..8a49ffef69 100644
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -229,8 +229,7 @@ Maybe<TextureHost::ResourceUpdateOp> AsyncImagePipelineManager::UpdateImageKeys(
auto* wrapper = aTexture ? aTexture->AsRemoteTextureHostWrapper() : nullptr;
if (wrapper && !aPipeline->mImageHost->GetAsyncRef()) {
std::function<void(const RemoteTextureInfo&)> function;
- RemoteTextureMap::Get()->GetRemoteTexture(
- wrapper, std::move(function), /* aWaitForRemoteTextureOwner */ false);
+ RemoteTextureMap::Get()->GetRemoteTexture(wrapper, std::move(function));
}
if (!aTexture || aTexture->NumSubTextures() == 0) {
diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp
index 789476cb6b..83139b6af6 100644
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -141,7 +141,7 @@ void gfx_wr_set_crash_annotation(mozilla::wr::CrashAnnotation aAnnotation,
return;
}
- CrashReporter::AnnotateCrashReport(annotation, nsDependentCString(aValue));
+ CrashReporter::RecordAnnotationCString(annotation, aValue);
}
void gfx_wr_clear_crash_annotation(mozilla::wr::CrashAnnotation aAnnotation) {
@@ -150,7 +150,7 @@ void gfx_wr_clear_crash_annotation(mozilla::wr::CrashAnnotation aAnnotation) {
return;
}
- CrashReporter::RemoveCrashReportAnnotation(annotation);
+ CrashReporter::UnrecordAnnotation(annotation);
}
}
@@ -1188,7 +1188,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
IsRootWebRenderBridgeParent());
if (!IsRootWebRenderBridgeParent()) {
- CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aTxnURL);
+ CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
+ aTxnURL);
}
CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
@@ -1330,7 +1331,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
IsRootWebRenderBridgeParent());
if (!IsRootWebRenderBridgeParent()) {
- CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aTxnURL);
+ CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
+ aTxnURL);
}
AUTO_PROFILER_TRACING_MARKER("Paint", "EmptyTransaction", GRAPHICS);
diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp
index e3bbd5d50f..5016bc30f8 100644
--- a/gfx/layers/wr/WebRenderImageHost.cpp
+++ b/gfx/layers/wr/WebRenderImageHost.cpp
@@ -198,8 +198,11 @@ void WebRenderImageHost::UseRemoteTexture() {
while (!mPendingRemoteTextureWrappers.empty()) {
auto* wrapper =
mPendingRemoteTextureWrappers.front()->AsRemoteTextureHostWrapper();
- mWaitingReadyCallback = RemoteTextureMap::Get()->GetRemoteTexture(
- wrapper, readyCallback, mWaitForRemoteTextureOwner);
+ if (mWaitForRemoteTextureOwner) {
+ RemoteTextureMap::Get()->WaitForRemoteTextureOwner(wrapper);
+ }
+ mWaitingReadyCallback =
+ RemoteTextureMap::Get()->GetRemoteTexture(wrapper, readyCallback);
MOZ_ASSERT_IF(mWaitingReadyCallback, !wrapper->IsReadyForRendering());
if (!wrapper->IsReadyForRendering()) {
break;
@@ -213,9 +216,9 @@ void WebRenderImageHost::UseRemoteTexture() {
mPendingRemoteTextureWrappers.pop_front();
MOZ_ASSERT(mPendingRemoteTextureWrappers.empty());
- std::function<void(const RemoteTextureInfo&)> function;
- RemoteTextureMap::Get()->GetRemoteTexture(wrapper, std::move(function),
- mWaitForRemoteTextureOwner);
+ if (mWaitForRemoteTextureOwner) {
+ RemoteTextureMap::Get()->WaitForRemoteTextureOwner(wrapper);
+ }
mWaitForRemoteTextureOwner = false;
}
diff --git a/gfx/layers/wr/WebRenderScrollData.cpp b/gfx/layers/wr/WebRenderScrollData.cpp
index 538df8bdef..905b7e1de0 100644
--- a/gfx/layers/wr/WebRenderScrollData.cpp
+++ b/gfx/layers/wr/WebRenderScrollData.cpp
@@ -370,6 +370,22 @@ void WebRenderScrollData::ApplyUpdates(ScrollUpdatesMap&& aUpdates,
mPaintSequenceNumber = aPaintSequenceNumber;
}
+void WebRenderScrollData::PrependUpdates(
+ const WebRenderScrollData& aPreviousData) {
+ for (auto previousMetadata : aPreviousData.mScrollMetadatas) {
+ const nsTArray<ScrollPositionUpdate>& previousUpdates =
+ previousMetadata.GetScrollUpdates();
+ if (previousUpdates.IsEmpty()) {
+ continue;
+ }
+
+ if (Maybe<size_t> index =
+ HasMetadataFor(previousMetadata.GetMetrics().GetScrollId())) {
+ mScrollMetadatas[*index].PrependUpdates(previousUpdates);
+ }
+ }
+}
+
void WebRenderScrollData::DumpSubtree(std::ostream& aOut, size_t aIndex,
const std::string& aIndent) const {
aOut << aIndent;
diff --git a/gfx/layers/wr/WebRenderScrollData.h b/gfx/layers/wr/WebRenderScrollData.h
index c575d4ca21..fd82ac93fc 100644
--- a/gfx/layers/wr/WebRenderScrollData.h
+++ b/gfx/layers/wr/WebRenderScrollData.h
@@ -276,6 +276,13 @@ class WebRenderScrollData {
void ApplyUpdates(ScrollUpdatesMap&& aUpdates, uint32_t aPaintSequenceNumber);
+ // Prepend the scroll position updates in the previous data to this data so
+ // that we can handle all scroll position updates in the proper order.
+ void PrependUpdates(const WebRenderScrollData& aPreviousData);
+
+ void SetWasUpdateSkipped() { mWasUpdateSkipped = true; }
+ bool GetWasUpdateSkipped() const { return mWasUpdateSkipped; }
+
friend struct IPC::ParamTraits<WebRenderScrollData>;
friend std::ostream& operator<<(std::ostream& aOut,
@@ -328,6 +335,12 @@ class WebRenderScrollData {
bool mIsFirstPaint;
uint32_t mPaintSequenceNumber;
+
+ // Wether this data was skipped to updated because the parent process hasn't
+ // yet gotten the referent LayersId for this data.
+ //
+ // Note this variable is not copied over IPC.
+ bool mWasUpdateSkipped = false;
};
} // namespace layers
diff --git a/gfx/ots/src/ots.h b/gfx/ots/src/ots.h
index 434e068d48..7e3625c737 100644
--- a/gfx/ots/src/ots.h
+++ b/gfx/ots/src/ots.h
@@ -87,8 +87,7 @@ class Buffer {
if (n_bytes > 1024 * 1024 * 1024) {
return OTS_FAILURE();
}
- if ((offset_ + n_bytes > length_) ||
- (offset_ > length_ - n_bytes)) {
+ if (length_ < n_bytes || offset_ > length_ - n_bytes) {
return OTS_FAILURE();
}
if (buf) {
@@ -99,7 +98,7 @@ class Buffer {
}
inline bool ReadU8(uint8_t *value) {
- if (offset_ + 1 > length_) {
+ if (length_ < 1 || offset_ > length_ - 1) {
return OTS_FAILURE();
}
*value = buffer_[offset_];
@@ -108,7 +107,7 @@ class Buffer {
}
bool ReadU16(uint16_t *value) {
- if (offset_ + 2 > length_) {
+ if (length_ < 2 || offset_ > length_ - 2) {
return OTS_FAILURE();
}
std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
@@ -122,7 +121,7 @@ class Buffer {
}
bool ReadU24(uint32_t *value) {
- if (offset_ + 3 > length_) {
+ if (length_ < 3 || offset_ > length_ - 3) {
return OTS_FAILURE();
}
*value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
@@ -133,7 +132,7 @@ class Buffer {
}
bool ReadU32(uint32_t *value) {
- if (offset_ + 4 > length_) {
+ if (length_ < 4 || offset_ > length_ - 4) {
return OTS_FAILURE();
}
std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
@@ -147,7 +146,7 @@ class Buffer {
}
bool ReadR64(uint64_t *value) {
- if (offset_ + 8 > length_) {
+ if (length_ < 8 || offset_ > length_ - 8) {
return OTS_FAILURE();
}
std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
diff --git a/gfx/ots/src/stat.cc b/gfx/ots/src/stat.cc
index f6f65fdf60..0eeaffb1c6 100644
--- a/gfx/ots/src/stat.cc
+++ b/gfx/ots/src/stat.cc
@@ -48,10 +48,6 @@ bool OpenTypeSTAT::Parse(const uint8_t* data, size_t length) {
this->minorVersion = 2;
}
- if (this->designAxisSize < sizeof(AxisRecord)) {
- return Drop("Invalid designAxisSize");
- }
-
size_t headerEnd = table.offset();
if (this->designAxisCount == 0) {
@@ -60,9 +56,13 @@ bool OpenTypeSTAT::Parse(const uint8_t* data, size_t length) {
this->designAxesOffset = 0;
}
} else {
+ if (this->designAxisSize < sizeof(AxisRecord)) {
+ return Drop("Invalid designAxisSize");
+ }
if (this->designAxesOffset < headerEnd ||
- size_t(this->designAxesOffset) +
- size_t(this->designAxisCount) * size_t(this->designAxisSize) > length) {
+ size_t(this->designAxesOffset) > length ||
+ size_t(this->designAxisCount) * size_t(this->designAxisSize) >
+ length - size_t(this->designAxesOffset)) {
return Drop("Invalid designAxesOffset");
}
}
@@ -95,8 +95,9 @@ bool OpenTypeSTAT::Parse(const uint8_t* data, size_t length) {
}
} else {
if (this->offsetToAxisValueOffsets < headerEnd ||
- size_t(this->offsetToAxisValueOffsets) +
- size_t(this->axisValueCount) * sizeof(uint16_t) > length) {
+ size_t(this->offsetToAxisValueOffsets) > length ||
+ size_t(this->axisValueCount) * sizeof(uint16_t) >
+ length - size_t(this->offsetToAxisValueOffsets)) {
return Drop("Invalid offsetToAxisValueOffsets");
}
}
@@ -107,7 +108,9 @@ bool OpenTypeSTAT::Parse(const uint8_t* data, size_t length) {
if (!table.ReadU16(&axisValueOffset)) {
return Drop("Failed to read axis value offset");
}
- if (this->offsetToAxisValueOffsets + axisValueOffset > length) {
+ // We already checked that offsetToAxisValueOffsets doesn't exceed length,
+ // so this subtraction will not underflow.
+ if (axisValueOffset > length - this->offsetToAxisValueOffsets) {
return Drop("Invalid axis value offset");
}
table.set_offset(this->offsetToAxisValueOffsets + axisValueOffset);
diff --git a/gfx/qcms/Cargo.toml b/gfx/qcms/Cargo.toml
index 094d1183d1..c6e0e76722 100644
--- a/gfx/qcms/Cargo.toml
+++ b/gfx/qcms/Cargo.toml
@@ -20,3 +20,6 @@ cmyk = []
[dependencies]
libc = {version = "0.2", optional = true }
+
+[build-dependencies]
+version_check = "0.9"
diff --git a/gfx/qcms/build.rs b/gfx/qcms/build.rs
new file mode 100644
index 0000000000..6810a8828e
--- /dev/null
+++ b/gfx/qcms/build.rs
@@ -0,0 +1,7 @@
+extern crate version_check as rustc;
+
+fn main() {
+ if rustc::is_min_version("1.78.0").unwrap_or(false) {
+ println!("cargo:rustc-cfg=stdsimd_split");
+ }
+}
diff --git a/gfx/qcms/src/iccread.rs b/gfx/qcms/src/iccread.rs
index ad45a58d35..ba2b5a3257 100644
--- a/gfx/qcms/src/iccread.rs
+++ b/gfx/qcms/src/iccread.rs
@@ -61,9 +61,7 @@ pub struct Profile {
pub(crate) mAB: Option<Box<lutmABType>>,
pub(crate) mBA: Option<Box<lutmABType>>,
pub(crate) chromaticAdaption: Option<Matrix>,
- pub(crate) output_table_r: Option<Arc<PrecacheOuput>>,
- pub(crate) output_table_g: Option<Arc<PrecacheOuput>>,
- pub(crate) output_table_b: Option<Arc<PrecacheOuput>>,
+ pub(crate) precache_output: Option<Arc<PrecacheOuput>>,
is_srgb: bool,
}
diff --git a/gfx/qcms/src/lib.rs b/gfx/qcms/src/lib.rs
index c311964ee3..fc496816a8 100644
--- a/gfx/qcms/src/lib.rs
+++ b/gfx/qcms/src/lib.rs
@@ -7,9 +7,11 @@
#![allow(non_upper_case_globals)]
// These are needed for the neon SIMD code and can be removed once the MSRV supports the
// instrinsics we use
-#![cfg_attr(feature = "neon", feature(stdsimd))]
+#![cfg_attr(all(stdsimd_split, target_arch = "arm", feature = "neon"), feature(stdarch_arm_neon_intrinsics))]
+#![cfg_attr(all(stdsimd_split, target_arch = "arm", feature = "neon"), feature(stdarch_arm_feature_detection))]
+#![cfg_attr(all(not(stdsimd_split), target_arch = "arm", feature = "neon"), feature(stdsimd))]
#![cfg_attr(
- feature = "neon",
+ all(target_arch = "arm", feature = "neon"),
feature(arm_target_feature, raw_ref_op)
)]
diff --git a/gfx/qcms/src/transform.rs b/gfx/qcms/src/transform.rs
index b0c8b60b18..54f89864eb 100644
--- a/gfx/qcms/src/transform.rs
+++ b/gfx/qcms/src/transform.rs
@@ -73,13 +73,17 @@ pub struct PrecacheOuput {
* improve startup performance and reduce memory usage. ColorSync on
* 10.5 uses 4097 which is perhaps because they use a fixed point
* representation where 1. is represented by 0x1000. */
- pub data: [u8; PRECACHE_OUTPUT_SIZE],
+ pub lut_r: [u8; PRECACHE_OUTPUT_SIZE],
+ pub lut_g: [u8; PRECACHE_OUTPUT_SIZE],
+ pub lut_b: [u8; PRECACHE_OUTPUT_SIZE],
}
impl Default for PrecacheOuput {
fn default() -> PrecacheOuput {
PrecacheOuput {
- data: [0; PRECACHE_OUTPUT_SIZE],
+ lut_r: [0; PRECACHE_OUTPUT_SIZE],
+ lut_g: [0; PRECACHE_OUTPUT_SIZE],
+ lut_b: [0; PRECACHE_OUTPUT_SIZE],
}
}
}
@@ -113,9 +117,7 @@ pub struct qcms_transform {
pub output_gamma_lut_g_length: usize,
pub output_gamma_lut_b_length: usize,
pub output_gamma_lut_gray_length: usize,
- pub output_table_r: Option<Arc<PrecacheOuput>>,
- pub output_table_g: Option<Arc<PrecacheOuput>>,
- pub output_table_b: Option<Arc<PrecacheOuput>>,
+ pub precache_output: Option<Arc<PrecacheOuput>>,
pub transform_fn: transform_fn_t,
}
@@ -414,15 +416,15 @@ unsafe extern "C" fn qcms_transform_data_gray_template_lut<I: GrayFormat, F: For
let out_device_r: f32 = lut_interp_linear(
linear as f64,
- &(*transform).output_gamma_lut_r.as_ref().unwrap(),
+ &transform.output_gamma_lut_r.as_ref().unwrap(),
);
let out_device_g: f32 = lut_interp_linear(
linear as f64,
- &(*transform).output_gamma_lut_g.as_ref().unwrap(),
+ &transform.output_gamma_lut_g.as_ref().unwrap(),
);
let out_device_b: f32 = lut_interp_linear(
linear as f64,
- &(*transform).output_gamma_lut_b.as_ref().unwrap(),
+ &transform.output_gamma_lut_b.as_ref().unwrap(),
);
*dest.add(F::kRIndex) = clamp_u8(out_device_r * 255f32);
*dest.add(F::kGIndex) = clamp_u8(out_device_g * 255f32);
@@ -475,17 +477,18 @@ unsafe fn qcms_transform_data_graya_bgra_out_lut(
qcms_transform_data_gray_template_lut::<GrayAlpha, BGRA>(transform, src, dest, length);
}
unsafe fn qcms_transform_data_gray_template_precache<I: GrayFormat, F: Format>(
- transform: *const qcms_transform,
+ transform: &qcms_transform,
mut src: *const u8,
mut dest: *mut u8,
length: usize,
) {
let components: u32 = if F::kAIndex == 0xff { 3 } else { 4 } as u32;
- let output_table_r = ((*transform).output_table_r).as_deref().unwrap();
- let output_table_g = ((*transform).output_table_g).as_deref().unwrap();
- let output_table_b = ((*transform).output_table_b).as_deref().unwrap();
+ let precache_output = transform.precache_output.as_deref().unwrap();
+ let output_r = &precache_output.lut_r;
+ let output_g = &precache_output.lut_g;
+ let output_b = &precache_output.lut_b;
- let input_gamma_table_gray = (*transform)
+ let input_gamma_table_gray = transform
.input_gamma_table_gray
.as_ref()
.unwrap()
@@ -506,9 +509,9 @@ unsafe fn qcms_transform_data_gray_template_precache<I: GrayFormat, F: Format>(
let linear: f32 = *input_gamma_table_gray.offset(device as isize);
/* we could round here... */
let gray: u16 = (linear * PRECACHE_OUTPUT_MAX as f32) as u16;
- *dest.add(F::kRIndex) = (output_table_r).data[gray as usize];
- *dest.add(F::kGIndex) = (output_table_g).data[gray as usize];
- *dest.add(F::kBIndex) = (output_table_b).data[gray as usize];
+ *dest.add(F::kRIndex) = output_r[gray as usize];
+ *dest.add(F::kGIndex) = output_g[gray as usize];
+ *dest.add(F::kBIndex) = output_b[gray as usize];
if F::kAIndex != 0xff {
*dest.add(F::kAIndex) = alpha
}
@@ -563,12 +566,12 @@ unsafe fn qcms_transform_data_template_lut_precache<F: Format>(
length: usize,
) {
let components: u32 = if F::kAIndex == 0xff { 3 } else { 4 } as u32;
- let output_table_r = ((*transform).output_table_r).as_deref().unwrap();
- let output_table_g = ((*transform).output_table_g).as_deref().unwrap();
- let output_table_b = ((*transform).output_table_b).as_deref().unwrap();
- let input_gamma_table_r = (*transform).input_gamma_table_r.as_ref().unwrap().as_ptr();
- let input_gamma_table_g = (*transform).input_gamma_table_g.as_ref().unwrap().as_ptr();
- let input_gamma_table_b = (*transform).input_gamma_table_b.as_ref().unwrap().as_ptr();
+ let output_table_r = &transform.precache_output.as_deref().unwrap().lut_r;
+ let output_table_g = &transform.precache_output.as_deref().unwrap().lut_g;
+ let output_table_b = &transform.precache_output.as_deref().unwrap().lut_b;
+ let input_gamma_table_r = transform.input_gamma_table_r.as_ref().unwrap().as_ptr();
+ let input_gamma_table_g = transform.input_gamma_table_g.as_ref().unwrap().as_ptr();
+ let input_gamma_table_b = transform.input_gamma_table_b.as_ref().unwrap().as_ptr();
let mat = &transform.matrix;
let mut i: u32 = 0;
@@ -596,9 +599,9 @@ unsafe fn qcms_transform_data_template_lut_precache<F: Format>(
let r: u16 = (out_linear_r * PRECACHE_OUTPUT_MAX as f32) as u16;
let g: u16 = (out_linear_g * PRECACHE_OUTPUT_MAX as f32) as u16;
let b: u16 = (out_linear_b * PRECACHE_OUTPUT_MAX as f32) as u16;
- *dest.add(F::kRIndex) = (output_table_r).data[r as usize];
- *dest.add(F::kGIndex) = (output_table_g).data[g as usize];
- *dest.add(F::kBIndex) = (output_table_b).data[b as usize];
+ *dest.add(F::kRIndex) = output_table_r[r as usize];
+ *dest.add(F::kGIndex) = output_table_g[g as usize];
+ *dest.add(F::kBIndex) = output_table_b[b as usize];
if F::kAIndex != 0xff {
*dest.add(F::kAIndex) = alpha
}
@@ -695,7 +698,7 @@ fn int_div_ceil(value: i32, div: i32) -> i32 {
}
// Using lcms' tetra interpolation algorithm.
unsafe extern "C" fn qcms_transform_data_tetra_clut_template<F: Format>(
- transform: *const qcms_transform,
+ transform: &qcms_transform,
mut src: *const u8,
mut dest: *mut u8,
length: usize,
@@ -703,9 +706,9 @@ unsafe extern "C" fn qcms_transform_data_tetra_clut_template<F: Format>(
let components: u32 = if F::kAIndex == 0xff { 3 } else { 4 } as u32;
let xy_len: i32 = 1;
- let x_len: i32 = (*transform).grid_size as i32;
+ let x_len: i32 = transform.grid_size as i32;
let len: i32 = x_len * x_len;
- let table = (*transform).clut.as_ref().unwrap().as_ptr();
+ let table = transform.clut.as_ref().unwrap().as_ptr();
let r_table: *const f32 = table;
let g_table: *const f32 = table.offset(1);
let b_table: *const f32 = table.offset(2);
@@ -735,15 +738,15 @@ unsafe extern "C" fn qcms_transform_data_tetra_clut_template<F: Format>(
let linear_r: f32 = in_r as i32 as f32 / 255.0;
let linear_g: f32 = in_g as i32 as f32 / 255.0;
let linear_b: f32 = in_b as i32 as f32 / 255.0;
- let x: i32 = in_r as i32 * ((*transform).grid_size as i32 - 1) / 255;
- let y: i32 = in_g as i32 * ((*transform).grid_size as i32 - 1) / 255;
- let z: i32 = in_b as i32 * ((*transform).grid_size as i32 - 1) / 255;
- let x_n: i32 = int_div_ceil(in_r as i32 * ((*transform).grid_size as i32 - 1), 255);
- let y_n: i32 = int_div_ceil(in_g as i32 * ((*transform).grid_size as i32 - 1), 255);
- let z_n: i32 = int_div_ceil(in_b as i32 * ((*transform).grid_size as i32 - 1), 255);
- let rx: f32 = linear_r * ((*transform).grid_size as i32 - 1) as f32 - x as f32;
- let ry: f32 = linear_g * ((*transform).grid_size as i32 - 1) as f32 - y as f32;
- let rz: f32 = linear_b * ((*transform).grid_size as i32 - 1) as f32 - z as f32;
+ let x: i32 = in_r as i32 * (transform.grid_size as i32 - 1) / 255;
+ let y: i32 = in_g as i32 * (transform.grid_size as i32 - 1) / 255;
+ let z: i32 = in_b as i32 * (transform.grid_size as i32 - 1) / 255;
+ let x_n: i32 = int_div_ceil(in_r as i32 * (transform.grid_size as i32 - 1), 255);
+ let y_n: i32 = int_div_ceil(in_g as i32 * (transform.grid_size as i32 - 1), 255);
+ let z_n: i32 = int_div_ceil(in_b as i32 * (transform.grid_size as i32 - 1), 255);
+ let rx: f32 = linear_r * (transform.grid_size as i32 - 1) as f32 - x as f32;
+ let ry: f32 = linear_g * (transform.grid_size as i32 - 1) as f32 - y as f32;
+ let rz: f32 = linear_b * (transform.grid_size as i32 - 1) as f32 - z as f32;
let CLU = |table: *const f32, x, y, z| {
*table.offset(((x * len + y * x_len + z * xy_len) * 3) as isize)
};
@@ -848,17 +851,17 @@ unsafe fn tetra(
let linear_g: f32 = in_g as i32 as f32 / 255.0;
let linear_b: f32 = in_b as i32 as f32 / 255.0;
let xy_len: i32 = 1;
- let x_len: i32 = (*transform).grid_size as i32;
+ let x_len: i32 = transform.grid_size as i32;
let len: i32 = x_len * x_len;
- let x: i32 = in_r as i32 * ((*transform).grid_size as i32 - 1) / 255;
- let y: i32 = in_g as i32 * ((*transform).grid_size as i32 - 1) / 255;
- let z: i32 = in_b as i32 * ((*transform).grid_size as i32 - 1) / 255;
- let x_n: i32 = int_div_ceil(in_r as i32 * ((*transform).grid_size as i32 - 1), 255);
- let y_n: i32 = int_div_ceil(in_g as i32 * ((*transform).grid_size as i32 - 1), 255);
- let z_n: i32 = int_div_ceil(in_b as i32 * ((*transform).grid_size as i32 - 1), 255);
- let rx: f32 = linear_r * ((*transform).grid_size as i32 - 1) as f32 - x as f32;
- let ry: f32 = linear_g * ((*transform).grid_size as i32 - 1) as f32 - y as f32;
- let rz: f32 = linear_b * ((*transform).grid_size as i32 - 1) as f32 - z as f32;
+ let x: i32 = in_r as i32 * (transform.grid_size as i32 - 1) / 255;
+ let y: i32 = in_g as i32 * (transform.grid_size as i32 - 1) / 255;
+ let z: i32 = in_b as i32 * (transform.grid_size as i32 - 1) / 255;
+ let x_n: i32 = int_div_ceil(in_r as i32 * (transform.grid_size as i32 - 1), 255);
+ let y_n: i32 = int_div_ceil(in_g as i32 * (transform.grid_size as i32 - 1), 255);
+ let z_n: i32 = int_div_ceil(in_b as i32 * (transform.grid_size as i32 - 1), 255);
+ let rx: f32 = linear_r * (transform.grid_size as i32 - 1) as f32 - x as f32;
+ let ry: f32 = linear_g * (transform.grid_size as i32 - 1) as f32 - y as f32;
+ let rz: f32 = linear_b * (transform.grid_size as i32 - 1) as f32 - z as f32;
let CLU = |table: *const f32, x, y, z| {
*table.offset(((x * len + y * x_len + z * xy_len) * 3) as isize)
};
@@ -966,9 +969,9 @@ unsafe fn qcms_transform_data_tetra_clut_cmyk(
mut dest: *mut u8,
length: usize,
) {
- let table = (*transform).clut.as_ref().unwrap().as_ptr();
+ let table = transform.clut.as_ref().unwrap().as_ptr();
assert!(
- (*transform).clut.as_ref().unwrap().len()
+ transform.clut.as_ref().unwrap().len()
>= ((transform.grid_size as i32).pow(4) * 3) as usize
);
for _ in 0..length {
@@ -978,10 +981,10 @@ unsafe fn qcms_transform_data_tetra_clut_cmyk(
let k: u8 = *src.add(3);
src = src.offset(4);
let linear_k: f32 = k as i32 as f32 / 255.0;
- let grid_size = (*transform).grid_size as i32;
- let w: i32 = k as i32 * ((*transform).grid_size as i32 - 1) / 255;
- let w_n: i32 = int_div_ceil(k as i32 * ((*transform).grid_size as i32 - 1), 255);
- let t: f32 = linear_k * ((*transform).grid_size as i32 - 1) as f32 - w as f32;
+ let grid_size = transform.grid_size as i32;
+ let w: i32 = k as i32 * (transform.grid_size as i32 - 1) / 255;
+ let w_n: i32 = int_div_ceil(k as i32 * (transform.grid_size as i32 - 1), 255);
+ let t: f32 = linear_k * (transform.grid_size as i32 - 1) as f32 - w as f32;
let table1 = table.offset((w * grid_size * grid_size * grid_size * 3) as isize);
let table2 = table.offset((w_n * grid_size * grid_size * grid_size * 3) as isize);
@@ -1032,9 +1035,9 @@ unsafe fn qcms_transform_data_template_lut<F: Format>(
let mat = &transform.matrix;
let mut i: u32 = 0;
- let input_gamma_table_r = (*transform).input_gamma_table_r.as_ref().unwrap().as_ptr();
- let input_gamma_table_g = (*transform).input_gamma_table_g.as_ref().unwrap().as_ptr();
- let input_gamma_table_b = (*transform).input_gamma_table_b.as_ref().unwrap().as_ptr();
+ let input_gamma_table_r = transform.input_gamma_table_r.as_ref().unwrap().as_ptr();
+ let input_gamma_table_g = transform.input_gamma_table_g.as_ref().unwrap().as_ptr();
+ let input_gamma_table_b = transform.input_gamma_table_b.as_ref().unwrap().as_ptr();
while (i as usize) < length {
let device_r: u8 = *src.add(F::kRIndex);
let device_g: u8 = *src.add(F::kGIndex);
@@ -1057,15 +1060,15 @@ unsafe fn qcms_transform_data_template_lut<F: Format>(
let out_device_r: f32 = lut_interp_linear(
out_linear_r as f64,
- &(*transform).output_gamma_lut_r.as_ref().unwrap(),
+ &transform.output_gamma_lut_r.as_ref().unwrap(),
);
let out_device_g: f32 = lut_interp_linear(
out_linear_g as f64,
- (*transform).output_gamma_lut_g.as_ref().unwrap(),
+ transform.output_gamma_lut_g.as_ref().unwrap(),
);
let out_device_b: f32 = lut_interp_linear(
out_linear_b as f64,
- (*transform).output_gamma_lut_b.as_ref().unwrap(),
+ transform.output_gamma_lut_b.as_ref().unwrap(),
);
*dest.add(F::kRIndex) = clamp_u8(out_device_r * 255f32);
*dest.add(F::kGIndex) = clamp_u8(out_device_g * 255f32);
@@ -1172,33 +1175,22 @@ pub extern "C" fn qcms_profile_precache_output_transform(profile: &mut Profile)
if profile.redTRC.is_none() || profile.greenTRC.is_none() || profile.blueTRC.is_none() {
return;
}
- if profile.output_table_r.is_none() {
- let mut output_table_r = precache_create();
- if compute_precache(
+ if profile.precache_output.is_none() {
+ let mut precache = precache_create();
+ compute_precache(
profile.redTRC.as_deref().unwrap(),
- &mut Arc::get_mut(&mut output_table_r).unwrap().data,
- ) {
- profile.output_table_r = Some(output_table_r);
- }
- }
- if profile.output_table_g.is_none() {
- let mut output_table_g = precache_create();
- if compute_precache(
+ &mut Arc::get_mut(&mut precache).unwrap().lut_r,
+ );
+ compute_precache(
profile.greenTRC.as_deref().unwrap(),
- &mut Arc::get_mut(&mut output_table_g).unwrap().data,
- ) {
- profile.output_table_g = Some(output_table_g);
- }
- }
- if profile.output_table_b.is_none() {
- let mut output_table_b = precache_create();
- if compute_precache(
+ &mut Arc::get_mut(&mut precache).unwrap().lut_g,
+ );
+ compute_precache(
profile.blueTRC.as_deref().unwrap(),
- &mut Arc::get_mut(&mut output_table_b).unwrap().data,
- ) {
- profile.output_table_b = Some(output_table_b);
- }
- };
+ &mut Arc::get_mut(&mut precache).unwrap().lut_b,
+ );
+ profile.precache_output = Some(precache);
+ }
}
/* Replace the current transformation with a LUT transformation using a given number of sample points */
fn transform_precacheLUT_float(
@@ -1225,16 +1217,16 @@ fn transform_precacheLUT_float(
}
let lut = chain_transform(input, output, src, dest, lutSize as usize);
if let Some(lut) = lut {
- (*transform).clut = Some(lut);
- (*transform).grid_size = samples as u16;
+ transform.clut = Some(lut);
+ transform.grid_size = samples as u16;
if in_type == RGBA8 {
- (*transform).transform_fn = Some(qcms_transform_data_tetra_clut_rgba)
+ transform.transform_fn = Some(qcms_transform_data_tetra_clut_rgba)
} else if in_type == BGRA8 {
- (*transform).transform_fn = Some(qcms_transform_data_tetra_clut_bgra)
+ transform.transform_fn = Some(qcms_transform_data_tetra_clut_bgra)
} else if in_type == RGB8 {
- (*transform).transform_fn = Some(qcms_transform_data_tetra_clut_rgb)
+ transform.transform_fn = Some(qcms_transform_data_tetra_clut_rgb)
}
- debug_assert!((*transform).transform_fn.is_some());
+ debug_assert!(transform.transform_fn.is_some());
} else {
return None;
}
@@ -1303,10 +1295,7 @@ pub fn transform_create(
}
let mut transform: Box<qcms_transform> = Box::new(Default::default());
let mut precache: bool = false;
- if output.output_table_r.is_some()
- && output.output_table_g.is_some()
- && output.output_table_b.is_some()
- {
+ if output.precache_output.is_some() {
precache = true
}
// This precache assumes RGB_SIGNATURE (fails on GRAY_SIGNATURE, for instance)
@@ -1330,9 +1319,7 @@ pub fn transform_create(
return result;
}
if precache {
- transform.output_table_r = Some(Arc::clone(output.output_table_r.as_ref().unwrap()));
- transform.output_table_g = Some(Arc::clone(output.output_table_g.as_ref().unwrap()));
- transform.output_table_b = Some(Arc::clone(output.output_table_b.as_ref().unwrap()));
+ transform.precache_output = Some(Arc::clone(output.precache_output.as_ref().unwrap()));
} else {
if output.redTRC.is_none() || output.greenTRC.is_none() || output.blueTRC.is_none() {
return None;
diff --git a/gfx/qcms/src/transform_avx.rs b/gfx/qcms/src/transform_avx.rs
index 3a000e56ba..04ca752a83 100644
--- a/gfx/qcms/src/transform_avx.rs
+++ b/gfx/qcms/src/transform_avx.rs
@@ -24,33 +24,33 @@ unsafe extern "C" fn qcms_transform_data_template_lut_avx<F: Format>(
mut dest: *mut u8,
mut length: usize,
) {
- let mat: *const [f32; 4] = (*transform).matrix.as_ptr();
+ let mat: *const [f32; 4] = transform.matrix.as_ptr();
let mut input: Output = std::mem::zeroed();
/* share input and output locations to save having to keep the
* locations in separate registers */
let output: *const u32 = &mut input as *mut Output as *mut u32;
/* deref *transform now to avoid it in loop */
- let igtbl_r: *const f32 = (*transform).input_gamma_table_r.as_ref().unwrap().as_ptr();
- let igtbl_g: *const f32 = (*transform).input_gamma_table_g.as_ref().unwrap().as_ptr();
- let igtbl_b: *const f32 = (*transform).input_gamma_table_b.as_ref().unwrap().as_ptr();
+ let igtbl_r: *const f32 = transform.input_gamma_table_r.as_ref().unwrap().as_ptr();
+ let igtbl_g: *const f32 = transform.input_gamma_table_g.as_ref().unwrap().as_ptr();
+ let igtbl_b: *const f32 = transform.input_gamma_table_b.as_ref().unwrap().as_ptr();
/* deref *transform now to avoid it in loop */
- let otdata_r: *const u8 = (*transform)
- .output_table_r
+ let otdata_r: *const u8 = transform
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_r
.as_ptr();
let otdata_g: *const u8 = (*transform)
- .output_table_g
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_g
.as_ptr();
let otdata_b: *const u8 = (*transform)
- .output_table_b
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_b
.as_ptr();
/* input matrix values never change */
let mat0: __m256 = _mm256_broadcast_ps(&*((*mat.offset(0isize)).as_ptr() as *const __m128));
diff --git a/gfx/qcms/src/transform_neon.rs b/gfx/qcms/src/transform_neon.rs
index b14b67107d..121b52ff52 100644
--- a/gfx/qcms/src/transform_neon.rs
+++ b/gfx/qcms/src/transform_neon.rs
@@ -25,23 +25,23 @@ unsafe fn qcms_transform_data_template_lut_neon<F: Format>(
let igtbl_g: *const f32 = (*transform).input_gamma_table_g.as_ref().unwrap().as_ptr();
let igtbl_b: *const f32 = (*transform).input_gamma_table_b.as_ref().unwrap().as_ptr();
/* deref *transform now to avoid it in loop */
- let otdata_r: *const u8 = (*transform)
- .output_table_r
+ let otdata_r: *const u8 = transform
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_r
.as_ptr();
let otdata_g: *const u8 = (*transform)
- .output_table_g
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_g
.as_ptr();
let otdata_b: *const u8 = (*transform)
- .output_table_b
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_b
.as_ptr();
/* input matrix values never change */
let mat0: float32x4_t = vld1q_f32((*mat.offset(0isize)).as_ptr());
diff --git a/gfx/qcms/src/transform_sse2.rs b/gfx/qcms/src/transform_sse2.rs
index f6bccaadc3..865a01be1c 100644
--- a/gfx/qcms/src/transform_sse2.rs
+++ b/gfx/qcms/src/transform_sse2.rs
@@ -30,22 +30,22 @@ unsafe extern "C" fn qcms_transform_data_template_lut_sse2<F: Format>(
let igtbl_b: *const f32 = (*transform).input_gamma_table_b.as_ref().unwrap().as_ptr();
/* deref *transform now to avoid it in loop */
let otdata_r: *const u8 = (*transform)
- .output_table_r
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_r
.as_ptr();
let otdata_g: *const u8 = (*transform)
- .output_table_g
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_g
.as_ptr();
let otdata_b: *const u8 = (*transform)
- .output_table_b
+ .precache_output
.as_deref()
.unwrap()
- .data
+ .lut_b
.as_ptr();
/* input matrix values never change */
let mat0: __m128 = _mm_load_ps((*mat.offset(0isize)).as_ptr());
diff --git a/gfx/qcms/src/transform_util.rs b/gfx/qcms/src/transform_util.rs
index 75fd2ca0e2..f341ae7946 100644
--- a/gfx/qcms/src/transform_util.rs
+++ b/gfx/qcms/src/transform_util.rs
@@ -471,7 +471,7 @@ pub fn compute_precache_linear(output: &mut [u8; PRECACHE_OUTPUT_SIZE]) {
output[v] = (v / (PRECACHE_OUTPUT_SIZE / 256)) as u8;
}
}
-pub(crate) fn compute_precache(trc: &curveType, output: &mut [u8; PRECACHE_OUTPUT_SIZE]) -> bool {
+pub(crate) fn compute_precache(trc: &curveType, output: &mut [u8; PRECACHE_OUTPUT_SIZE]) {
match trc {
curveType::Parametric(params) => {
let mut gamma_table_uint: [u16; 256] = [0; 256];
@@ -512,7 +512,6 @@ pub(crate) fn compute_precache(trc: &curveType, output: &mut [u8; PRECACHE_OUTPU
}
}
}
- true
}
fn build_linear_table(length: usize) -> Vec<u16> {
let mut output = Vec::with_capacity(length);
diff --git a/gfx/skia/skia/src/ports/SkTypeface_mac_ct.cpp b/gfx/skia/skia/src/ports/SkTypeface_mac_ct.cpp
index 362245ec45..ebeda314d8 100644
--- a/gfx/skia/skia/src/ports/SkTypeface_mac_ct.cpp
+++ b/gfx/skia/skia/src/ports/SkTypeface_mac_ct.cpp
@@ -64,7 +64,7 @@
#include <string.h>
#include <memory>
-#ifdef MOZ_SKIA
+#if defined(MOZ_SKIA) && defined(XP_MACOSX)
#include "nsCocoaFeatures.h"
#endif
@@ -290,7 +290,7 @@ SkUniqueCFRef<CTFontRef> SkCTFontCreateExactCopy(CTFontRef baseFont, CGFloat tex
auto ctFont = SkUniqueCFRef<CTFontRef>(
CTFontCreateWithGraphicsFont(baseCGFont.get(), textSize, nullptr, desc.get()));
if (variations) {
-#ifdef MOZ_SKIA
+#if defined(MOZ_SKIA) && defined(XP_MACOSX)
if (nsCocoaFeatures::OnVenturaOrLater()) {
// On recent macOS versions, CTFontCreateWithGraphicsFont fails to apply
// the variations from the descriptor, so to get the correct values we use
diff --git a/gfx/src/DriverCrashGuard.cpp b/gfx/src/DriverCrashGuard.cpp
index 9b68c07e55..c54a07b9ec 100644
--- a/gfx/src/DriverCrashGuard.cpp
+++ b/gfx/src/DriverCrashGuard.cpp
@@ -156,7 +156,7 @@ DriverCrashGuard::~DriverCrashGuard() {
dom::ContentChild::GetSingleton()->SendEndDriverCrashGuard(uint32_t(mType));
}
- CrashReporter::RemoveCrashReportAnnotation(
+ CrashReporter::UnrecordAnnotation(
CrashReporter::Annotation::GraphicsStartupTest);
}
@@ -195,7 +195,7 @@ void DriverCrashGuard::ActivateGuard() {
// attribute a random parent process crash to a graphics problem in a child
// process.
if (mMode != Mode::Proxy) {
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationBool(
CrashReporter::Annotation::GraphicsStartupTest, true);
}
diff --git a/gfx/tests/browser/browser_native_font_cache_macos.js b/gfx/tests/browser/browser_native_font_cache_macos.js
index 919a5c7a72..e71ccbf5a6 100644
--- a/gfx/tests/browser/browser_native_font_cache_macos.js
+++ b/gfx/tests/browser/browser_native_font_cache_macos.js
@@ -87,8 +87,9 @@ add_task(async () => {
const nfrm_match = nfrm_line.exec(copiedText);
if (nfrm_match) {
const nfrm_mb = nfrm_match[1];
- ok(
- nfrm_mb < MB_EXCLUSIVE_MAX,
+ Assert.less(
+ nfrm_mb,
+ MB_EXCLUSIVE_MAX,
`native-font-resource-mac ${nfrm_mb} MB should be less than ${MB_EXCLUSIVE_MAX} MB.`
);
} else {
@@ -102,8 +103,9 @@ add_task(async () => {
const gfx_match = gfx_line.exec(copiedText);
if (gfx_match && gfx_match.index < om_match.index) {
const gfx_mb = gfx_match[1];
- ok(
- gfx_mb < MB_EXCLUSIVE_MAX,
+ Assert.less(
+ gfx_mb,
+ MB_EXCLUSIVE_MAX,
`Explicit Allocations gfx ${gfx_mb} MB should be less than ${MB_EXCLUSIVE_MAX} MB.`
);
} else {
diff --git a/gfx/tests/browser/browser_windowless_troubleshoot_crash.js b/gfx/tests/browser/browser_windowless_troubleshoot_crash.js
index 44fc50e2f8..2ccae78a6e 100644
--- a/gfx/tests/browser/browser_windowless_troubleshoot_crash.js
+++ b/gfx/tests/browser/browser_windowless_troubleshoot_crash.js
@@ -1,10 +1,10 @@
add_task(async function test_windowlessBrowserTroubleshootCrash() {
let webNav = Services.appShell.createWindowlessBrowser(false);
- let onLoaded = new Promise((resolve, reject) => {
+ let onLoaded = new Promise(resolve => {
let docShell = webNav.docShell;
let listener = {
- observe(contentWindow, topic, data) {
+ observe(contentWindow) {
let observedDocShell =
contentWindow.docShell.sameTypeRootTreeItem.QueryInterface(
Ci.nsIDocShell
@@ -45,8 +45,9 @@ add_task(async function test_windowlessBrowserTroubleshootCrash() {
);
var data = await Troubleshoot.snapshot();
- ok(
- data.graphics.windowLayerManagerType !== "None",
+ Assert.notStrictEqual(
+ data.graphics.windowLayerManagerType,
+ "None",
"windowless browser window should not set windowLayerManagerType to 'None'"
);
diff --git a/gfx/tests/chrome/test_device_reset.html b/gfx/tests/chrome/test_device_reset.html
index a081c26dc4..167dff1b7b 100644
--- a/gfx/tests/chrome/test_device_reset.html
+++ b/gfx/tests/chrome/test_device_reset.html
@@ -70,7 +70,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1274663
windowutils.triggerDeviceReset();
SimpleTest.waitForExplicitFinish();
- window.addEventListener("MozAfterPaint", function paintHandle(e) {
+ window.addEventListener("MozAfterPaint", function paintHandle() {
// Add more latency before calling runCanvasTest()
// runCanvasTest() needs to be called after gecko's device reset handling.
// Since Bug 1757879 fix, the triggerDeviceReset() does the device reset
diff --git a/gfx/tests/crashtests/1701975-1.html b/gfx/tests/crashtests/1701975-1.html
deleted file mode 100644
index c7d54ca996..0000000000
--- a/gfx/tests/crashtests/1701975-1.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <style>
- #id_0 {
- font-size: 10000% ! important
- }
-
- * {
- border-top-style: groove;
- }
- </style>
-
-</head>
-<math>
- <semantics style='border-inline: 1000000em outset !important'>
- <mmultiscripts id='id_0'></mmultiscripts>
- </semantics>
-</math>
-</html>
diff --git a/gfx/tests/crashtests/306902-1.xml b/gfx/tests/crashtests/306902-1.xml
deleted file mode 100644
index 24e8c068a0..0000000000
--- a/gfx/tests/crashtests/306902-1.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version='1.0'?>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
-<body>
-
-<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'><msup>
-
-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
-</msup></math>
-
-</body>
-</html>
diff --git a/gfx/tests/crashtests/385289-1.xhtml b/gfx/tests/crashtests/385289-1.xhtml
deleted file mode 100644
index 666756c016..0000000000
--- a/gfx/tests/crashtests/385289-1.xhtml
+++ /dev/null
@@ -1,30 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<script>
-function boom()
-{
- var mss = document.getElementById("mss");
-
- var j = document.createTextNode("j");
- var comb = document.createTextNode("\u0302");
-
- mss.appendChild(j);
- mss.appendChild(comb);
-}
-</script>
-</head>
-
-<body onload="boom()">
-
-<div>
- <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
- <msub id="mss">
- <mi>v</mi>
- <mn>1</mn>
- </msub>
- </math>
-</div>
-
-</body>
-
-</html>
diff --git a/gfx/tests/crashtests/410728-1.xml b/gfx/tests/crashtests/410728-1.xml
deleted file mode 100644
index deaeb8fc55..0000000000
--- a/gfx/tests/crashtests/410728-1.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE html PUBLIC
- "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
- "http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd"
-[
- <!ENTITY mathml "http://www.w3.org/1998/Math/MathML">
-]>
-<math display="block" xmlns="&mathml;">
- <mi>f &#x0332;</mi>
- <mi>-</mi>
- <mo>+</mo>
- <mo> -</mo>
- <mo>&#x0332;</mo>
-</math>
diff --git a/gfx/tests/crashtests/crashtests.list b/gfx/tests/crashtests/crashtests.list
index d3c9efef11..44a2f61050 100644
--- a/gfx/tests/crashtests/crashtests.list
+++ b/gfx/tests/crashtests/crashtests.list
@@ -5,7 +5,6 @@ load 199379-1.html
load 206561-1.html
load 248518-1.html
load 306649-1.xml
-load 306902-1.xml
load 333861-1.html
load 334735-1.html
load 345576-1.html
@@ -24,7 +23,6 @@ load 383473-1.html
load 383872-1.svg
load 385228-1.svg
skip load 385228-2.svg # bug 523255 / bug 385228
-load 385289-1.xhtml
load 385417-1.html
load 385417-2.html
load 385423-1.html
@@ -32,7 +30,7 @@ load 385423-2.html
load 385719-1.html
load 389326-1.html
load 390476.html
-skip-if(xulRuntime.OS=="WINNT"&&!xulRuntime.is64Bit) load 393746-1.xhtml # Bug 1727925
+skip-if(winWidget&&!is64Bit) load 393746-1.xhtml # Bug 1727925
load 393749-1.html
load 393822-1.html
load 394384-1.html
@@ -53,7 +51,6 @@ load 405268-1.xhtml
load 407761-1.html
load 407842.html
load 408754-1.html
-load 410728-1.xml
load 416637-1.html
load 419095-1.html
load 419255-1.html
@@ -205,7 +202,6 @@ load 1694783-1.html
load 1695782-1.html
load 1699013.html
load 1700232.html
-load 1701975-1.html
load 1704321-1.html
load 1702638.html
load 1730695.html
diff --git a/gfx/tests/gtest/TestConfigManager.cpp b/gfx/tests/gtest/TestConfigManager.cpp
index d76dcfd234..825a995e98 100644
--- a/gfx/tests/gtest/TestConfigManager.cpp
+++ b/gfx/tests/gtest/TestConfigManager.cpp
@@ -159,6 +159,12 @@ class MockGfxInfo final : public nsIGfxInfo {
NS_IMETHOD GetUsingGPUProcess(bool* aOutValue) override {
return NS_ERROR_NOT_IMPLEMENTED;
}
+ NS_IMETHOD GetUsingRemoteCanvas(bool* aOutValue) override {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+ NS_IMETHOD GetUsingAcceleratedCanvas(bool* aOutValue) override {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
NS_IMETHOD GetIsHeadless(bool* aIsHeadless) override {
return NS_ERROR_NOT_IMPLEMENTED;
}
diff --git a/gfx/tests/reftest/reftest.list b/gfx/tests/reftest/reftest.list
index bb081d5c06..dcdac53c67 100644
--- a/gfx/tests/reftest/reftest.list
+++ b/gfx/tests/reftest/reftest.list
@@ -2,7 +2,7 @@
== 468496-1.html 468496-1-ref.html
fuzzy(0-175,0-443) == 611498-1.html 611498-ref.html
skip-if(gtkWidget||Android||isDebugBuild) fuzzy-if(appleSilicon,0-1,0-9) == 709477-1.html 709477-1-ref.html #Bug 1620096
-skip-if(!asyncPan) == 1086723.html 1086723-ref.html
+skip-if(useDrawSnapshot) == 1086723.html 1086723-ref.html
== 853889-1.html 853889-1-ref.html
skip-if(Android) fuzzy(0-1,0-587) == 1143303-1.svg pass.svg
fuzzy(0-100,0-30) == 1149923.html 1149923-ref.html # use fuzzy due to few distorted pixels caused by border-radius
@@ -18,13 +18,13 @@ fuzzy-if(!useDrawSnapshot,0-5,0-1060) fuzzy-if(useDrawSnapshot,32-32,26350-26350
fuzzy(0-11,0-4) fails-if(useDrawSnapshot) == 1474722.html 1474722-ref.html
fails-if(useDrawSnapshot) == 1501195.html 1501195-ref.html
== 1519754.html 1519754-ref.html
-skip-if(!asyncPan) == 1524261.html 1524261-ref.html
+skip-if(useDrawSnapshot) == 1524261.html 1524261-ref.html
fuzzy-if(!useDrawSnapshot,14-14,44-95) == 1524353.html 1524353-ref.html
== 1523776.html 1523776-ref.html
== bug1523410-translate-scale-snap.html bug1523410-translate-scale-snap-ref.html
== 1523080.html 1523080-ref.html
== 1616444-same-color-different-paths.html 1616444-same-color-different-paths-ref.html
-skip-if(!asyncPan||Android) fuzzy-if(winWidget,54-94,2713-3419) fuzzy-if(cocoaWidget,24-24,1190-1200) pref(apz.allow_zooming,true) == picture-caching-on-async-zoom.html picture-caching-on-async-zoom.html?ref
+skip-if(useDrawSnapshot||Android) fuzzy-if(winWidget,54-94,2713-3419) fuzzy-if(cocoaWidget,24-24,1190-1200) pref(apz.allow_zooming,true) == picture-caching-on-async-zoom.html picture-caching-on-async-zoom.html?ref
pref(apz.allow_zooming,true) fails-if(useDrawSnapshot) == 1662062-1-no-blurry.html 1662062-1-ref.html
# Bug 1715676: nsBulletFrame has been removed and the new rendering does not use PushRoundedRect that this test is for:
# == 1681610.html 1681610-ref.html
@@ -32,7 +32,7 @@ skip-if(geckoview) fuzzy-if(!useDrawSnapshot,0-255,0-1050) fuzzy-if(useDrawSnaps
fuzzy(64-99,506-645) == 1696439-1.html 1696439-1-ref.html
random-if(gtkWidget) == 1722689-1.html 1722689-1-ref.html
fuzzy-if(useDrawSnapshot,255-255,5-5) == 1724901-1.html 1724901-1-ref.html
-pref(image.downscale-during-decode.enabled,true) skip-if(Android) fuzzy-if(useDrawSnapshot&&browserIsFission,203-203,193600-193600) HTTP == 1724901-2.html 1724901-2-ref.html
+pref(image.downscale-during-decode.enabled,true) skip-if(Android) fuzzy-if(useDrawSnapshot&&fission,203-203,193600-193600) HTTP == 1724901-2.html 1724901-2-ref.html
== 1760747-1.html 1760747-1-ref.html
!= 1761685-1.html 1761685-1-ref.html
fuzzy(0-9,0-305) == 1761460.html 1761460-ref.html
diff --git a/gfx/thebes/CoreTextFontList.cpp b/gfx/thebes/CoreTextFontList.cpp
index 0c8c179e8e..e83435b638 100644
--- a/gfx/thebes/CoreTextFontList.cpp
+++ b/gfx/thebes/CoreTextFontList.cpp
@@ -35,6 +35,15 @@
using namespace mozilla;
using namespace mozilla::gfx;
+#ifdef MOZ_WIDGET_COCOA
+// Building with newer macOS SDKs can cause a bunch of font-family names to be
+// hidden from the Core Text API we use to enumerate available fonts. Because
+// some content still benefits from having these names recognized, we forcibly
+// include them in the list. Some day we might want to drop support for these.
+# define USE_DEPRECATED_FONT_FAMILY_NAMES 1
+#endif
+
+#if USE_DEPRECATED_FONT_FAMILY_NAMES
// List generated by diffing the arrays returned by
// CTFontManagerCopyAvailableFontFamilyNames() when built with
// MACOSX_DEPLOYMENT_TARGET=10.12 vs 11.0, to identify the font family names
@@ -198,6 +207,7 @@ constexpr nsLiteralCString kDeprecatedFontFamilies[] = {
"Superclarendon"_ns,
"Times"_ns,
};
+#endif // USE_DEPRECATED_FONT_FAMILY_NAMES
static void GetStringForCFString(CFStringRef aSrc, nsAString& aDest) {
auto len = CFStringGetLength(aSrc);
@@ -497,7 +507,7 @@ CGFontRef CTFontEntry::CreateOrCopyFontRef() {
return mFontRef;
}
- CrashReporter::AutoAnnotateCrashReport autoFontName(
+ CrashReporter::AutoRecordAnnotation autoFontName(
CrashReporter::Annotation::FontName, mName);
// Create a new CGFont; caller will own the only reference to it.
@@ -666,7 +676,7 @@ bool CTFontEntry::SupportsOpenTypeFeature(Script aScript,
return mHasAATSmallCaps;
}
- CrashReporter::AutoAnnotateCrashReport autoFontName(
+ CrashReporter::AutoRecordAnnotation autoFontName(
CrashReporter::Annotation::FontName, FamilyName());
AutoCFRelease<CTFontRef> ctFont =
@@ -907,6 +917,47 @@ void CTFontFamily::FindStyleVariationsLocked(FontInfoData* aFontInfoData) {
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("CTFontFamily::FindStyleVariations",
LAYOUT, mName);
+ if (mForSystemFont) {
+ MOZ_ASSERT(gfxPlatform::HasVariationFontSupport());
+
+ auto addToFamily = [&](CTFontRef aFont) MOZ_REQUIRES(mLock) {
+ AutoCFRelease<CFStringRef> psName = CTFontCopyPostScriptName(aFont);
+ nsAutoString nameUTF16;
+ nsAutoCString nameUTF8;
+ GetStringForCFString(psName, nameUTF16);
+ CopyUTF16toUTF8(nameUTF16, nameUTF8);
+
+ auto* fe =
+ new CTFontEntry(nameUTF8, WeightRange(FontWeight::NORMAL), true, 0.0);
+
+ // Set the appropriate style, assuming it may not have a variation range.
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(aFont);
+ fe->mStyleRange = SlantStyleRange((traits & kCTFontTraitItalic)
+ ? FontSlantStyle::ITALIC
+ : FontSlantStyle::NORMAL);
+
+ // Set up weight (and width, if present) ranges.
+ fe->SetupVariationRanges();
+ AddFontEntryLocked(fe);
+ };
+
+ addToFamily(mForSystemFont);
+
+ // See if there is a corresponding italic face, and add it to the family.
+ AutoCFRelease<CTFontRef> italicFont = CTFontCreateCopyWithSymbolicTraits(
+ mForSystemFont, 0.0, nullptr, kCTFontTraitItalic, kCTFontTraitItalic);
+ if (italicFont != mForSystemFont) {
+ addToFamily(italicFont);
+ }
+
+ CFRelease(mForSystemFont);
+ mForSystemFont = nullptr;
+
+ SetHasStyles(true);
+
+ return;
+ }
+
struct Context {
CTFontFamily* family;
const void* prevValue = nullptr;
@@ -1134,11 +1185,13 @@ nsresult CoreTextFontList::InitFontListForPlatform() {
(CFStringRef)CFArrayGetValueAtIndex(familyNames, i);
AddFamily(familyName);
}
+#if USE_DEPRECATED_FONT_FAMILY_NAMES
for (const auto& name : kDeprecatedFontFamilies) {
if (DeprecatedFamilyIsAvailable(name)) {
AddFamily(name, GetVisibilityForFamily(name));
}
}
+#endif
} else {
// Content process: use font list passed from the chrome process via
// the GetXPCOMProcessAttributes message, because it's much faster than
@@ -1196,8 +1249,11 @@ void CoreTextFontList::InitSharedFontListForPlatform() {
AutoCFRelease<CFArrayRef> familyNames =
CTFontManagerCopyAvailableFontFamilyNames();
nsTArray<fontlist::Family::InitData> families;
- families.SetCapacity(CFArrayGetCount(familyNames) +
- ArrayLength(kDeprecatedFontFamilies));
+ families.SetCapacity(CFArrayGetCount(familyNames)
+#if USE_DEPRECATED_FONT_FAMILY_NAMES
+ + ArrayLength(kDeprecatedFontFamilies)
+#endif
+ );
for (CFIndex i = 0; i < CFArrayGetCount(familyNames); ++i) {
nsAutoString name16;
CFStringRef familyName =
@@ -1209,6 +1265,7 @@ void CoreTextFontList::InitSharedFontListForPlatform() {
families.AppendElement(fontlist::Family::InitData(
key, name, fontlist::Family::kNoIndex, GetVisibilityForFamily(name)));
}
+#if USE_DEPRECATED_FONT_FAMILY_NAMES
for (const nsACString& name : kDeprecatedFontFamilies) {
if (DeprecatedFamilyIsAvailable(name)) {
nsAutoCString key;
@@ -1218,6 +1275,7 @@ void CoreTextFontList::InitSharedFontListForPlatform() {
GetVisibilityForFamily(name)));
}
}
+#endif
SharedFontList()->SetFamilyNames(families);
InitAliasesForSingleFaceList();
GetPrefsAndStartLoader();
@@ -1367,7 +1425,7 @@ gfxFontEntry* CoreTextFontList::LookupLocalFont(
AutoLock lock(mLock);
- CrashReporter::AutoAnnotateCrashReport autoFontName(
+ CrashReporter::AutoRecordAnnotation autoFontName(
CrashReporter::Annotation::FontName, aFontName);
AutoCFRelease<CFStringRef> faceName = CreateCFStringForString(aFontName);
@@ -1444,7 +1502,7 @@ gfxFontEntry* CoreTextFontList::MakePlatformFont(const nsACString& aFontName,
return nullptr;
}
- CrashReporter::AutoAnnotateCrashReport autoFontName(
+ CrashReporter::AutoRecordAnnotation autoFontName(
CrashReporter::Annotation::FontName, aFontName);
AutoCFRelease<CGDataProviderRef> provider =
@@ -1504,7 +1562,7 @@ class CTFontInfo final : public FontInfoData {
};
void CTFontInfo::LoadFontFamilyData(const nsACString& aFamilyName) {
- CrashReporter::AutoAnnotateCrashReport autoFontName(
+ CrashReporter::AutoRecordAnnotation autoFontName(
CrashReporter::Annotation::FontName, aFamilyName);
// Prevent this from running concurrently with CGFont operations on the main
// thread, because the macOS font cache is fragile with concurrent access.
@@ -1726,7 +1784,7 @@ void CoreTextFontList::GetFacesInitDataForFamily(
const fontlist::Family* aFamily, nsTArray<fontlist::Face::InitData>& aFaces,
bool aLoadCmaps) const {
auto name = aFamily->Key().AsString(SharedFontList());
- CrashReporter::AutoAnnotateCrashReport autoFontName(
+ CrashReporter::AutoRecordAnnotation autoFontName(
CrashReporter::Annotation::FontName, name);
struct Context {
@@ -1805,6 +1863,56 @@ void CoreTextFontList::ReadFaceNamesForFamily(
}
}
+static CFStringRef CopyRealFamilyName(CTFontRef aFont) {
+ AutoCFRelease<CFStringRef> psName = CTFontCopyPostScriptName(aFont);
+ AutoCFRelease<CGFontRef> cgFont =
+ CGFontCreateWithFontName(CFStringRef(psName));
+ if (!cgFont) {
+ return CTFontCopyFamilyName(aFont);
+ }
+ AutoCFRelease<CTFontRef> ctFont =
+ CTFontCreateWithGraphicsFont(cgFont, 0.0, nullptr, nullptr);
+ if (!ctFont) {
+ return CTFontCopyFamilyName(aFont);
+ }
+ return CTFontCopyFamilyName(ctFont);
+}
+
+void CoreTextFontList::InitSystemFontNames() {
+ // text font family
+ AutoCFRelease<CTFontRef> font = CTFontCreateUIFontForLanguage(
+ kCTFontUIFontSystem, 0.0, nullptr); // TODO: language
+ AutoCFRelease<CFStringRef> name = CopyRealFamilyName(font);
+
+ nsAutoString familyName;
+ GetStringForCFString(name, familyName);
+ CopyUTF16toUTF8(familyName, mSystemFontFamilyName);
+
+ // We store an in-process gfxFontFamily for the system font even if using the
+ // shared fontlist to manage "normal" fonts, because the hidden system fonts
+ // may be excluded from the font list altogether. This family will be
+ // populated based on the given NSFont.
+ RefPtr<gfxFontFamily> fam = new CTFontFamily(mSystemFontFamilyName, font);
+ if (fam) {
+ nsAutoCString key;
+ GenerateFontListKey(mSystemFontFamilyName, key);
+ mFontFamilies.InsertOrUpdate(key, std::move(fam));
+ }
+}
+
+FontFamily CoreTextFontList::GetDefaultFontForPlatform(
+ nsPresContext* aPresContext, const gfxFontStyle* aStyle,
+ nsAtom* aLanguage) {
+ AutoCFRelease<CTFontRef> font = CTFontCreateUIFontForLanguage(
+ kCTFontUIFontUser, 0.0, nullptr); // TODO: language
+ AutoCFRelease<CFStringRef> name = CTFontCopyFamilyName(font);
+
+ nsAutoString familyName;
+ GetStringForCFString(name, familyName);
+
+ return FindFamily(aPresContext, NS_ConvertUTF16toUTF8(familyName));
+}
+
#ifdef MOZ_BUNDLED_FONTS
void CoreTextFontList::ActivateBundledFonts() {
nsCOMPtr<nsIFile> localDir;
diff --git a/gfx/thebes/CoreTextFontList.h b/gfx/thebes/CoreTextFontList.h
index 3aa7b75247..97052b36f6 100644
--- a/gfx/thebes/CoreTextFontList.h
+++ b/gfx/thebes/CoreTextFontList.h
@@ -118,6 +118,15 @@ class CTFontFamily : public gfxFontFamily {
CTFontFamily(const nsACString& aName, FontVisibility aVisibility)
: gfxFontFamily(aName, aVisibility) {}
+ CTFontFamily(const nsACString& aName, CTFontRef aSystemFont)
+ : gfxFontFamily(aName, FontVisibility::Unknown),
+ mForSystemFont(aSystemFont) {
+ // I don't think the system font instance is at much risk of being deleted,
+ // but to be on the safe side let's retain a reference until we're finished
+ // using it for lazy initialization.
+ CFRetain(mForSystemFont);
+ }
+
virtual ~CTFontFamily() = default;
void LocalizedName(nsACString& aLocalizedName) override;
@@ -127,6 +136,15 @@ class CTFontFamily : public gfxFontFamily {
protected:
void AddFace(CTFontDescriptorRef aFace) MOZ_REQUIRES(mLock);
+
+ // If non-null, this is a family representing the system UI font, and should
+ // use the given CTFontRef as the basis for initialization as the normal
+ // font-manager APIs based on family name won't handle it.
+ CTFontRef mForSystemFont = nullptr;
+};
+
+class gfxMacFontFamily final : public CTFontFamily {
+ public:
};
class CoreTextFontList : public gfxPlatformFontList {
@@ -179,7 +197,13 @@ class CoreTextFontList : public gfxPlatformFontList {
void PreloadNamesList() MOZ_REQUIRES(mLock);
// initialize system fonts
- virtual void InitSystemFontNames() = 0;
+ void InitSystemFontNames() MOZ_REQUIRES(mLock);
+
+ // look up a default font to use as fallback
+ FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
+ const gfxFontStyle* aStyle,
+ nsAtom* aLanguage = nullptr)
+ MOZ_REQUIRES(mLock) override;
// Hooks for the macOS-specific "single face family" hack (Osaka-mono).
virtual void InitSingleFaceList() {}
diff --git a/gfx/thebes/DeviceManagerDx.cpp b/gfx/thebes/DeviceManagerDx.cpp
index 18c5cea7db..ba473e0d1e 100644
--- a/gfx/thebes/DeviceManagerDx.cpp
+++ b/gfx/thebes/DeviceManagerDx.cpp
@@ -206,6 +206,129 @@ bool DeviceManagerDx::GetOutputFromMonitor(HMONITOR monitor,
return false;
}
+void DeviceManagerDx::PostUpdateMonitorInfo() {
+ MOZ_ASSERT(XRE_IsGPUProcess());
+ MOZ_ASSERT(NS_IsMainThread());
+
+ MutexAutoLock lock(mDeviceLock);
+ // Reduce frequency of UpdateMonitorInfo() call.
+ if (mUpdateMonitorInfoRunnable) {
+ return;
+ }
+
+ auto* holder = CompositorThreadHolder::GetSingleton();
+ if (!holder) {
+ return;
+ }
+
+ mUpdateMonitorInfoRunnable = NS_NewRunnableFunction(
+ "DeviceManagerDx::PostUpdateMonitorInfo::Runnable", []() -> void {
+ auto* dm = gfx::DeviceManagerDx::Get();
+ if (dm) {
+ dm->UpdateMonitorInfo();
+ }
+ });
+
+ const uint32_t kDelayMS = 100;
+ RefPtr<Runnable> runnable = mUpdateMonitorInfoRunnable;
+ holder->GetCompositorThread()->DelayedDispatch(runnable.forget(), kDelayMS);
+}
+
+void DeviceManagerDx::UpdateMonitorInfo() {
+ bool systemHdrEnabled = false;
+
+ for (const auto& desc : GetOutputDescs()) {
+ if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
+ systemHdrEnabled = true;
+ }
+ }
+ {
+ MutexAutoLock lock(mDeviceLock);
+ mSystemHdrEnabled = Some(systemHdrEnabled);
+ mUpdateMonitorInfoRunnable = nullptr;
+ }
+}
+
+std::vector<DXGI_OUTPUT_DESC1> DeviceManagerDx::GetOutputDescs() {
+ std::vector<DXGI_OUTPUT_DESC1> outputDescs;
+
+ nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll"));
+ decltype(CreateDXGIFactory1)* createDXGIFactory1 =
+ (decltype(CreateDXGIFactory1)*)GetProcAddress(dxgiModule,
+ "CreateDXGIFactory1");
+ if (!createDXGIFactory1) {
+ return outputDescs;
+ }
+
+ RefPtr<IDXGIFactory1> dxgiFactory;
+ HRESULT hr =
+ createDXGIFactory1(__uuidof(IDXGIFactory1), getter_AddRefs(dxgiFactory));
+ if (FAILED(hr)) {
+ gfxCriticalNoteOnce << "Failed to create DXGI factory: " << gfx::hexa(hr);
+ return outputDescs;
+ }
+
+ for (UINT adapterIndex = 0;; adapterIndex++) {
+ RefPtr<IDXGIAdapter> adapter;
+ hr = dxgiFactory->EnumAdapters(adapterIndex, getter_AddRefs(adapter));
+ if (hr == DXGI_ERROR_NOT_FOUND) {
+ break;
+ }
+ if (FAILED(hr)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ gfxCriticalNoteOnce << "Failed to enumerate DXGI adapter: "
+ << gfx::hexa(hr);
+ break;
+ }
+
+ for (UINT outputIndex = 0;; ++outputIndex) {
+ RefPtr<IDXGIOutput> output;
+ hr = adapter->EnumOutputs(outputIndex, getter_AddRefs(output));
+ if (hr == DXGI_ERROR_NOT_FOUND) {
+ break;
+ }
+ if (FAILED(hr)) {
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ gfxCriticalNoteOnce << "Failed to enumulate DXGI output: "
+ << gfx::hexa(hr);
+ break;
+ }
+
+ RefPtr<IDXGIOutput6> output6;
+ hr = output->QueryInterface(__uuidof(IDXGIOutput6),
+ getter_AddRefs(output6));
+ if (FAILED(hr)) {
+ continue;
+ }
+
+ DXGI_OUTPUT_DESC1 desc;
+ if (FAILED(output6->GetDesc1(&desc))) {
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ gfxCriticalNoteOnce << "Failed to get DXGI output descriptor";
+ continue;
+ }
+
+ outputDescs.push_back(std::move(desc));
+ }
+ }
+
+ return outputDescs;
+}
+
+bool DeviceManagerDx::SystemHDREnabled() {
+ {
+ MutexAutoLock lock(mDeviceLock);
+ if (mSystemHdrEnabled.isSome()) {
+ return mSystemHdrEnabled.ref();
+ }
+ }
+
+ UpdateMonitorInfo();
+
+ MutexAutoLock lock(mDeviceLock);
+ return mSystemHdrEnabled.ref();
+}
+
void DeviceManagerDx::CheckHardwareStretchingSupport(HwStretchingSupport& aRv) {
RefPtr<IDXGIAdapter> adapter = GetDXGIAdapter();
diff --git a/gfx/thebes/DeviceManagerDx.h b/gfx/thebes/DeviceManagerDx.h
index 9d127af358..c6860c7ffa 100644
--- a/gfx/thebes/DeviceManagerDx.h
+++ b/gfx/thebes/DeviceManagerDx.h
@@ -6,6 +6,8 @@
#ifndef mozilla_gfx_thebes_DeviceManagerDx_h
#define mozilla_gfx_thebes_DeviceManagerDx_h
+#include <vector>
+
#include "gfxPlatform.h"
#include "gfxTelemetry.h"
#include "gfxTypes.h"
@@ -88,6 +90,9 @@ class DeviceManagerDx final {
// 'monitor'; returns false if not found or some error occurred.
bool GetOutputFromMonitor(HMONITOR monitor, RefPtr<IDXGIOutput>* aOutOutput);
+ void PostUpdateMonitorInfo();
+ bool SystemHDREnabled();
+
// Check if the current adapter supports hardware stretching
void CheckHardwareStretchingSupport(HwStretchingSupport& aRv);
@@ -172,6 +177,9 @@ class DeviceManagerDx final {
bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason)
MOZ_REQUIRES(mDeviceLock);
+ void UpdateMonitorInfo();
+ std::vector<DXGI_OUTPUT_DESC1> GetOutputDescs();
+
private:
static StaticAutoPtr<DeviceManagerDx> sInstance;
@@ -198,6 +206,8 @@ class DeviceManagerDx final {
bool mCompositorDeviceSupportsVideo MOZ_GUARDED_BY(mDeviceLock);
Maybe<D3D11DeviceStatus> mDeviceStatus MOZ_GUARDED_BY(mDeviceLock);
Maybe<DeviceResetReason> mDeviceResetReason MOZ_GUARDED_BY(mDeviceLock);
+ RefPtr<Runnable> mUpdateMonitorInfoRunnable MOZ_GUARDED_BY(mDeviceLock);
+ Maybe<bool> mSystemHdrEnabled MOZ_GUARDED_BY(mDeviceLock);
nsModuleHandle mDirectDrawDLL;
RefPtr<IDirectDraw7> mDirectDraw;
diff --git a/gfx/thebes/IOSPlatformFontList.h b/gfx/thebes/IOSPlatformFontList.h
new file mode 100644
index 0000000000..733939b755
--- /dev/null
+++ b/gfx/thebes/IOSPlatformFontList.h
@@ -0,0 +1,36 @@
+/* -*- 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/. */
+
+#ifndef IOSPlatformFontList_H_
+#define IOSPlatformFontList_H_
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "CoreTextFontList.h"
+
+class IOSPlatformFontList final : public CoreTextFontList {
+ public:
+ static IOSPlatformFontList* PlatformFontList() {
+ return static_cast<IOSPlatformFontList*>(
+ gfxPlatformFontList::PlatformFontList());
+ }
+
+ static void LookupSystemFont(mozilla::LookAndFeel::FontID aSystemFontID,
+ nsACString& aSystemFontName,
+ gfxFontStyle& aFontStyle);
+
+ protected:
+ nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists()
+ override;
+
+ private:
+ friend class gfxPlatformMac;
+
+ // Only the friend class gfxPlatformMac constructs this.
+ IOSPlatformFontList();
+ virtual ~IOSPlatformFontList();
+};
+
+#endif /* IOSPlatformFontList_H_ */
diff --git a/gfx/thebes/IOSPlatformFontList.mm b/gfx/thebes/IOSPlatformFontList.mm
new file mode 100644
index 0000000000..e42d209fa3
--- /dev/null
+++ b/gfx/thebes/IOSPlatformFontList.mm
@@ -0,0 +1,24 @@
+/* -*- 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/. */
+
+#import <UIKit/UIKit.h>
+#include "IOSPlatformFontList.h"
+
+IOSPlatformFontList::IOSPlatformFontList() : CoreTextFontList() {}
+
+IOSPlatformFontList::~IOSPlatformFontList() {}
+
+void IOSPlatformFontList::LookupSystemFont(
+ mozilla::LookAndFeel::FontID aSystemFontID, nsACString& aSystemFontName,
+ gfxFontStyle& aFontStyle) {
+ MOZ_CRASH("UNIMPLEMENTED");
+}
+
+nsTArray<std::pair<const char**, uint32_t>>
+IOSPlatformFontList::GetFilteredPlatformFontLists() {
+ nsTArray<std::pair<const char**, uint32_t>> fontLists;
+
+ return fontLists;
+}
diff --git a/gfx/thebes/gencjkcisvs.py b/gfx/thebes/gencjkcisvs.py
index 6a28e7d492..000b3f5711 100644
--- a/gfx/thebes/gencjkcisvs.py
+++ b/gfx/thebes/gencjkcisvs.py
@@ -9,7 +9,7 @@ import sys
f = open(sys.argv[1] if len(sys.argv) > 1 else "StandardizedVariants.txt")
line = f.readline()
-m = re.compile("^# (StandardizedVariants(-\d+(\.\d+)*)?\.txt)").search(line)
+m = re.compile(r"^# (StandardizedVariants(-\d+(\.\d+)*)?\.txt)").search(line)
fileversion = m.group(1)
vsdict = {}
r = re.compile(
diff --git a/gfx/thebes/gfxCoreTextShaper.h b/gfx/thebes/gfxCoreTextShaper.h
index 53f24ba3ba..557b6ba247 100644
--- a/gfx/thebes/gfxCoreTextShaper.h
+++ b/gfx/thebes/gfxCoreTextShaper.h
@@ -8,7 +8,7 @@
#include "gfxFont.h"
-#include <ApplicationServices/ApplicationServices.h>
+#include <CoreText/CoreText.h>
class gfxMacFont;
diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp
index b77058b359..8595004d21 100644
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -1159,6 +1159,17 @@ FontVisibility gfxDWriteFontList::GetVisibilityForFamily(
return FontVisibility::User;
}
+nsTArray<std::pair<const char**, uint32_t>>
+gfxDWriteFontList::GetFilteredPlatformFontLists() {
+ nsTArray<std::pair<const char**, uint32_t>> fontLists;
+
+ fontLists.AppendElement(std::make_pair(kBaseFonts, ArrayLength(kBaseFonts)));
+ fontLists.AppendElement(
+ std::make_pair(kLangPackFonts, ArrayLength(kLangPackFonts)));
+
+ return fontLists;
+}
+
void gfxDWriteFontList::AppendFamiliesFromCollection(
IDWriteFontCollection* aCollection,
nsTArray<fontlist::Family::InitData>& aFamilies,
diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h
index adf8fdfa5a..357336a12c 100644
--- a/gfx/thebes/gfxDWriteFontList.h
+++ b/gfx/thebes/gfxDWriteFontList.h
@@ -436,6 +436,9 @@ class gfxDWriteFontList final : public gfxPlatformFontList {
FontFamily& aMatchedFamily)
MOZ_REQUIRES(mLock) override;
+ nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists()
+ override;
+
private:
friend class gfxDWriteFontFamily;
diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp
index 6ff9788dc1..66f7655282 100644
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -1321,6 +1321,55 @@ FontVisibility gfxFT2FontList::GetVisibilityForFamily(
return FontVisibility::User;
}
+nsTArray<std::pair<const char**, uint32_t>>
+gfxFT2FontList::GetFilteredPlatformFontLists() {
+ static Device fontVisibilityDevice = Device::Unassigned;
+ if (fontVisibilityDevice == Device::Unassigned) {
+ nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
+ Unused << gfxInfo->GetFontVisibilityDetermination(&fontVisibilityDevice);
+ }
+
+ nsTArray<std::pair<const char**, uint32_t>> fontLists;
+
+ if (fontVisibilityDevice == Device::Android_Unknown_Release_Version ||
+ fontVisibilityDevice == Device::Android_Unknown_Peloton ||
+ fontVisibilityDevice == Device::Android_Unknown_vbox ||
+ fontVisibilityDevice == Device::Android_Unknown_mitv ||
+ fontVisibilityDevice == Device::Android_Chromebook ||
+ fontVisibilityDevice == Device::Android_Amazon) {
+ return fontLists;
+ }
+
+ // Sanity Check
+ if (fontVisibilityDevice != Device::Android_sub_9 &&
+ fontVisibilityDevice != Device::Android_9_11 &&
+ fontVisibilityDevice != Device::Android_12_plus) {
+ return fontLists;
+ }
+
+ fontLists.AppendElement(
+ std::make_pair(kBaseFonts_Android, ArrayLength(kBaseFonts_Android)));
+
+ if (fontVisibilityDevice == Device::Android_sub_9) {
+ fontLists.AppendElement(std::make_pair(kBaseFonts_Android5_8,
+ ArrayLength(kBaseFonts_Android5_8)));
+ } else {
+ fontLists.AppendElement(std::make_pair(
+ kBaseFonts_Android9_Higher, ArrayLength(kBaseFonts_Android9_Higher)));
+
+ if (fontVisibilityDevice == Device::Android_9_11) {
+ fontLists.AppendElement(std::make_pair(
+ kBaseFonts_Android9_11, ArrayLength(kBaseFonts_Android9_11)));
+ } else {
+ fontLists.AppendElement(
+ std::make_pair(kBaseFonts_Android12_Higher,
+ ArrayLength(kBaseFonts_Android12_Higher)));
+ }
+ }
+
+ return fontLists;
+}
+
static void GetName(hb_face_t* aFace, hb_ot_name_id_t aNameID,
nsACString& aName) {
unsigned int n = 0;
diff --git a/gfx/thebes/gfxFT2FontList.h b/gfx/thebes/gfxFT2FontList.h
index 895b1172d4..0e92d31944 100644
--- a/gfx/thebes/gfxFT2FontList.h
+++ b/gfx/thebes/gfxFT2FontList.h
@@ -210,6 +210,9 @@ class gfxFT2FontList final : public gfxPlatformFontList {
void CollectInitData(const FontListEntry& aFLE, const nsCString& aPSName,
const nsCString& aFullName, StandardFile aStdFile);
+ nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists()
+ override;
+
/**
* Callback passed to AppendFacesFromCachedFaceList to collect family/face
* information in either the unshared or shared list we're building.
diff --git a/gfx/thebes/gfxFcPlatformFontList.cpp b/gfx/thebes/gfxFcPlatformFontList.cpp
index 60a8f9894e..30c202d6ee 100644
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -2048,6 +2048,49 @@ FontVisibility gfxFcPlatformFontList::GetVisibilityForFamily(
}
}
+nsTArray<std::pair<const char**, uint32_t>>
+gfxFcPlatformFontList::GetFilteredPlatformFontLists() {
+ AssignFontVisibilityDevice();
+
+ nsTArray<std::pair<const char**, uint32_t>> fontLists;
+
+ switch (sFontVisibilityDevice) {
+ case Device::Linux_Ubuntu_any:
+ case Device::Linux_Ubuntu_22:
+ fontLists.AppendElement(std::make_pair(
+ kBaseFonts_Ubuntu_22_04, ArrayLength(kBaseFonts_Ubuntu_22_04)));
+ fontLists.AppendElement(std::make_pair(
+ kLangFonts_Ubuntu_22_04, ArrayLength(kLangFonts_Ubuntu_22_04)));
+ // For Ubuntu_any, we fall through to also check the 20_04 lists.
+ [[fallthrough]];
+
+ case Device::Linux_Ubuntu_20:
+ fontLists.AppendElement(std::make_pair(
+ kBaseFonts_Ubuntu_20_04, ArrayLength(kBaseFonts_Ubuntu_20_04)));
+ fontLists.AppendElement(std::make_pair(
+ kLangFonts_Ubuntu_20_04, ArrayLength(kLangFonts_Ubuntu_20_04)));
+ break;
+
+ case Device::Linux_Fedora_any:
+ case Device::Linux_Fedora_39:
+ fontLists.AppendElement(std::make_pair(
+ kBaseFonts_Fedora_39, ArrayLength(kBaseFonts_Fedora_39)));
+ // For Fedora_any, fall through to also check Fedora 38 list.
+ [[fallthrough]];
+
+ case Device::Linux_Fedora_38:
+ fontLists.AppendElement(std::make_pair(
+ kBaseFonts_Fedora_38, ArrayLength(kBaseFonts_Fedora_38)));
+ break;
+
+ default:
+ // We don't know how to categorize fonts on this system
+ break;
+ }
+
+ return fontLists;
+}
+
gfxFontEntry* gfxFcPlatformFontList::CreateFontEntry(
fontlist::Face* aFace, const fontlist::Family* aFamily) {
nsAutoCString desc(aFace->mDescriptor.AsString(SharedFontList()));
diff --git a/gfx/thebes/gfxFcPlatformFontList.h b/gfx/thebes/gfxFcPlatformFontList.h
index 54070d1410..ebf57fbcaa 100644
--- a/gfx/thebes/gfxFcPlatformFontList.h
+++ b/gfx/thebes/gfxFcPlatformFontList.h
@@ -317,6 +317,9 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList {
protected:
virtual ~gfxFcPlatformFontList();
+ nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists()
+ override;
+
#if defined(MOZ_SANDBOX) && defined(XP_LINUX)
typedef mozilla::SandboxBroker::Policy SandboxPolicy;
#else
diff --git a/gfx/thebes/gfxFontUtils.cpp b/gfx/thebes/gfxFontUtils.cpp
index 02543607cd..46f33f4696 100644
--- a/gfx/thebes/gfxFontUtils.cpp
+++ b/gfx/thebes/gfxFontUtils.cpp
@@ -28,7 +28,7 @@
#include "plbase64.h"
#include "mozilla/Logging.h"
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
# include <CoreFoundation/CoreFoundation.h>
#endif
@@ -1441,7 +1441,7 @@ bool gfxFontUtils::DecodeFontName(const char* aNameData, int32_t aByteLen,
}
if (encoding == X_USER_DEFINED_ENCODING) {
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
// Special case for macOS only: support legacy Mac encodings
// that aren't part of the Encoding Standard.
if (aPlatformCode == PLATFORM_ID_MAC) {
diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp
index 3c4c7bce07..4dca4506c0 100644
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -853,6 +853,13 @@ bool gfxGDIFontList::FindAndAddFamiliesLocked(
aDevToCssSize);
}
+nsTArray<std::pair<const char**, uint32_t>>
+gfxGDIFontList::GetFilteredPlatformFontLists() {
+ nsTArray<std::pair<const char**, uint32_t>> fontLists;
+
+ return fontLists;
+}
+
FontFamily gfxGDIFontList::GetDefaultFontForPlatform(
nsPresContext* aPresContext, const gfxFontStyle* aStyle,
nsAtom* aLanguage) {
diff --git a/gfx/thebes/gfxGDIFontList.h b/gfx/thebes/gfxGDIFontList.h
index 708f7fc114..7fc7f7521b 100644
--- a/gfx/thebes/gfxGDIFontList.h
+++ b/gfx/thebes/gfxGDIFontList.h
@@ -332,6 +332,9 @@ class gfxGDIFontList final : public gfxPlatformFontList {
nsAtom* aLanguage = nullptr)
MOZ_REQUIRES(mLock) override;
+ nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists()
+ override;
+
private:
friend class gfxWindowsPlatform;
diff --git a/gfx/thebes/gfxMacFont.h b/gfx/thebes/gfxMacFont.h
index f33ad478ec..051c4ea675 100644
--- a/gfx/thebes/gfxMacFont.h
+++ b/gfx/thebes/gfxMacFont.h
@@ -8,7 +8,7 @@
#include "mozilla/MemoryReporting.h"
#include "gfxFont.h"
-#include <ApplicationServices/ApplicationServices.h>
+#include <CoreText/CoreText.h>
#include "mozilla/gfx/UnscaledFontMac.h"
diff --git a/gfx/thebes/gfxMacPlatformFontList.h b/gfx/thebes/gfxMacPlatformFontList.h
index ac0d8927fe..8bafa1b803 100644
--- a/gfx/thebes/gfxMacPlatformFontList.h
+++ b/gfx/thebes/gfxMacPlatformFontList.h
@@ -17,6 +17,9 @@ class gfxMacPlatformFontList final : public CoreTextFontList {
gfxPlatformFontList::PlatformFontList());
}
+ nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists()
+ override;
+
static void LookupSystemFont(mozilla::LookAndFeel::FontID aSystemFontID,
nsACString& aSystemFontName,
gfxFontStyle& aFontStyle);
@@ -25,11 +28,6 @@ class gfxMacPlatformFontList final : public CoreTextFontList {
bool DeprecatedFamilyIsAvailable(const nsACString& aName) override;
FontVisibility GetVisibilityForFamily(const nsACString& aName) const override;
- FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
- const gfxFontStyle* aStyle,
- nsAtom* aLanguage = nullptr)
- MOZ_REQUIRES(mLock) override;
-
private:
friend class gfxPlatformMac;
@@ -40,9 +38,6 @@ class gfxMacPlatformFontList final : public CoreTextFontList {
void InitSingleFaceList() MOZ_REQUIRES(mLock) override;
void InitAliasesForSingleFaceList() MOZ_REQUIRES(mLock) override;
- // initialize system fonts
- void InitSystemFontNames() override MOZ_REQUIRES(mLock);
-
nsTArray<nsCString> mSingleFaceFonts;
};
diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm
index e36c9c8a25..2b8d1fa16a 100644
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -72,80 +72,6 @@ static NSString* GetNSStringForString(const nsAString& aSrc) {
#define LOG_CMAPDATA_ENABLED() \
MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_cmapdata), mozilla::LogLevel::Debug)
-class gfxMacFontFamily final : public CTFontFamily {
- public:
- gfxMacFontFamily(const nsACString& aName, NSFont* aSystemFont)
- : CTFontFamily(aName, FontVisibility::Unknown),
- mForSystemFont(aSystemFont) {
- // I don't think the system font instance is at much risk of being deleted,
- // but to be on the safe side let's retain a reference until we're finished
- // using it for lazy initialization.
- [mForSystemFont retain];
- }
-
- void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr)
- MOZ_REQUIRES(mLock) override;
-
- protected:
- // If non-null, this is a family representing the system UI font, and should
- // use the given NSFont as the basis for initialization as the normal
- // font-manager APIs based on family name won't handle it.
- NSFont* mForSystemFont = nullptr;
-};
-
-void gfxMacFontFamily::FindStyleVariationsLocked(FontInfoData* aFontInfoData) {
- if (mHasStyles) {
- return;
- }
-
- AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("gfxMacFontFamily::FindStyleVariations",
- LAYOUT, mName);
-
- nsAutoreleasePool localPool;
-
- if (mForSystemFont) {
- MOZ_ASSERT(gfxPlatform::HasVariationFontSupport());
-
- auto addToFamily = [&](NSFont* aNSFont) MOZ_REQUIRES(mLock) {
- NSString* psNameNS = aNSFont.fontDescriptor.postscriptName;
- nsAutoString nameUTF16;
- nsAutoCString psName;
- nsCocoaUtils::GetStringForNSString(psNameNS, nameUTF16);
- CopyUTF16toUTF8(nameUTF16, psName);
-
- auto* fe =
- new CTFontEntry(psName, WeightRange(FontWeight::NORMAL), true, 0.0);
-
- // Set the appropriate style, assuming it may not have a variation range.
- fe->mStyleRange = SlantStyleRange(
- (aNSFont.fontDescriptor.symbolicTraits & NSFontItalicTrait)
- ? FontSlantStyle::ITALIC
- : FontSlantStyle::NORMAL);
-
- // Set up weight (and width, if present) ranges.
- fe->SetupVariationRanges();
- AddFontEntryLocked(fe);
- };
-
- addToFamily(mForSystemFont);
-
- // See if there is a corresponding italic face, and add it to the family.
- NSFont* italicFont = [sFontManager convertFont:mForSystemFont
- toHaveTrait:NSItalicFontMask];
- if (italicFont != mForSystemFont) {
- addToFamily(italicFont);
- }
-
- [mForSystemFont release];
- mForSystemFont = nullptr;
- SetHasStyles(true);
-
- return;
- }
-
- CTFontFamily::FindStyleVariationsLocked(aFontInfoData);
-}
-
/* gfxSingleFaceMacFontFamily */
class gfxSingleFaceMacFontFamily final : public gfxFontFamily {
@@ -252,6 +178,15 @@ FontVisibility gfxMacPlatformFontList::GetVisibilityForFamily(
return FontVisibility::User;
}
+nsTArray<std::pair<const char**, uint32_t>>
+gfxMacPlatformFontList::GetFilteredPlatformFontLists() {
+ nsTArray<std::pair<const char**, uint32_t>> fontLists;
+
+ fontLists.AppendElement(std::make_pair(kBaseFonts, ArrayLength(kBaseFonts)));
+
+ return fontLists;
+}
+
bool gfxMacPlatformFontList::DeprecatedFamilyIsAvailable(
const nsACString& aName) {
NSString* family = GetNSStringForString(NS_ConvertUTF8toUTF16(aName));
@@ -394,92 +329,6 @@ void gfxMacPlatformFontList::InitSingleFaceList() {
}
}
-// System fonts under OSX may contain weird "meta" names but if we create
-// a new font using just the Postscript name, the NSFont api returns an object
-// with the actual real family name. For example, under OSX 10.11:
-//
-// [[NSFont menuFontOfSize:8.0] familyName] ==> .AppleSystemUIFont
-// [[NSFont fontWithName:[[[NSFont menuFontOfSize:8.0] fontDescriptor]
-// postscriptName]
-// size:8.0] familyName] ==> .SF NS Text
-
-static NSString* GetRealFamilyName(NSFont* aFont) {
- NSString* psName = [[aFont fontDescriptor] postscriptName];
- // With newer macOS versions and SDKs (e.g. when compiled against SDK 10.15),
- // [NSFont fontWithName:] fails for hidden system fonts, because the
- // underlying Core Text functions it uses reject such names and tell us to use
- // the special CTFontCreateUIFontForLanguage API instead. To work around this,
- // as we don't yet work directly with the CTFontUIFontType identifiers, we
- // create a Core Graphics font (as it doesn't reject system font names), and
- // use this to create a Core Text font that we can query for the family name.
- // Eventually we should move to using CTFontUIFontType constants to identify
- // system fonts, and eliminate the need to instantiate them (indirectly) from
- // their postscript names.
- AutoCFRelease<CGFontRef> cgFont =
- CGFontCreateWithFontName(CFStringRef(psName));
- if (!cgFont) {
- return [aFont familyName];
- }
-
- AutoCFRelease<CTFontRef> ctFont =
- CTFontCreateWithGraphicsFont(cgFont, 0.0, nullptr, nullptr);
- if (!ctFont) {
- return [aFont familyName];
- }
- NSString* familyName = (NSString*)CTFontCopyFamilyName(ctFont);
-
- return [familyName autorelease];
-}
-
-void gfxMacPlatformFontList::InitSystemFontNames() {
- // text font family
- NSFont* sys = [NSFont systemFontOfSize:0.0];
- NSString* textFamilyName = GetRealFamilyName(sys);
- nsAutoString familyName;
- nsCocoaUtils::GetStringForNSString(textFamilyName, familyName);
- CopyUTF16toUTF8(familyName, mSystemFontFamilyName);
-
- // We store an in-process gfxFontFamily for the system font even if using the
- // shared fontlist to manage "normal" fonts, because the hidden system fonts
- // may be excluded from the font list altogether. This family will be
- // populated based on the given NSFont.
- RefPtr<gfxFontFamily> fam = new gfxMacFontFamily(mSystemFontFamilyName, sys);
- if (fam) {
- nsAutoCString key;
- GenerateFontListKey(mSystemFontFamilyName, key);
- mFontFamilies.InsertOrUpdate(key, std::move(fam));
- }
-
-#ifdef DEBUG
- // different system font API's always map to the same family under OSX, so
- // just assume that and emit a warning if that ever changes
- NSString* sysFamily = GetRealFamilyName([NSFont systemFontOfSize:0.0]);
- if ([sysFamily compare:GetRealFamilyName([NSFont
- boldSystemFontOfSize:0.0])] != NSOrderedSame ||
- [sysFamily compare:GetRealFamilyName([NSFont
- controlContentFontOfSize:0.0])] != NSOrderedSame ||
- [sysFamily compare:GetRealFamilyName([NSFont menuBarFontOfSize:0.0])] !=
- NSOrderedSame ||
- [sysFamily compare:GetRealFamilyName([NSFont toolTipsFontOfSize:0.0])] !=
- NSOrderedSame) {
- NS_WARNING("system font types map to different font families"
- " -- please log a bug!!");
- }
-#endif
-}
-
-FontFamily gfxMacPlatformFontList::GetDefaultFontForPlatform(
- nsPresContext* aPresContext, const gfxFontStyle* aStyle,
- nsAtom* aLanguage) {
- nsAutoreleasePool localPool;
-
- NSString* defaultFamily = [[NSFont userFontOfSize:aStyle->size] familyName];
- nsAutoString familyName;
-
- GetStringForNSString(defaultFamily, familyName);
- return FindFamily(aPresContext, NS_ConvertUTF16toUTF8(familyName));
-}
-
void gfxMacPlatformFontList::LookupSystemFont(LookAndFeel::FontID aSystemFontID,
nsACString& aSystemFontName,
gfxFontStyle& aFontStyle) {
diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp
index ccc76def7e..c57564b054 100644
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -21,8 +21,8 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/GraphicsMessages.h"
-#include "mozilla/gfx/CanvasManagerChild.h"
#include "mozilla/gfx/CanvasRenderThread.h"
+#include "mozilla/gfx/CanvasShutdownManager.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/EnumTypeTraits.h"
@@ -79,7 +79,7 @@
#if defined(XP_WIN)
# include "gfxWindowsPlatform.h"
# include "mozilla/widget/WinWindowOcclusionTracker.h"
-#elif defined(XP_MACOSX)
+#elif defined(XP_DARWIN)
# include "gfxPlatformMac.h"
# include "gfxQuartzSurface.h"
#elif defined(MOZ_WIDGET_GTK)
@@ -289,9 +289,8 @@ void CrashStatsLogForwarder::UpdateCrashReport() {
<< " (t=" << std::get<2>(it) << ") ";
}
- nsCString reportString(message.str().c_str());
- nsresult annotated =
- CrashReporter::AnnotateCrashReport(mCrashCriticalKey, reportString);
+ nsresult annotated = CrashReporter::RecordAnnotationCString(
+ mCrashCriticalKey, message.str().c_str());
if (annotated != NS_OK) {
printf("Crash Annotation %s: %s",
@@ -409,7 +408,7 @@ void CrashStatsLogForwarder::CrashAction(LogReason aReason) {
#define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
#define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
-#if defined(XP_MACOSX)
+#if defined(XP_DARWIN)
# define GFX_PREF_CORETEXT_SHAPING "gfx.font_rendering.coretext.enabled"
#endif
@@ -786,7 +785,7 @@ bool gfxPlatform::HasVariationFontSupport() {
// as any thread will set it to the same value.
#if defined(XP_WIN)
sHasVariationFontSupport = gfxWindowsPlatform::CheckVariationFontSupport();
-#elif defined(XP_MACOSX)
+#elif defined(XP_DARWIN)
sHasVariationFontSupport = gfxPlatformMac::CheckVariationFontSupport();
#elif defined(MOZ_WIDGET_GTK)
sHasVariationFontSupport = gfxPlatformGtk::CheckVariationFontSupport();
@@ -904,7 +903,7 @@ void gfxPlatform::Init() {
#if defined(XP_WIN)
gPlatform = new gfxWindowsPlatform;
-#elif defined(XP_MACOSX)
+#elif defined(XP_DARWIN)
gPlatform = new gfxPlatformMac;
#elif defined(MOZ_WIDGET_GTK)
gPlatform = new gfxPlatformGtk;
@@ -1069,6 +1068,15 @@ void gfxPlatform::ReportTelemetry() {
nsString adapterDesc;
gfxInfo->GetAdapterDescription(adapterDesc);
+
+// Android description is constructed in a way that makes it possible to exceed
+// the metric's length limit.
+#if defined(ANDROID)
+ if (!adapterDesc.IsEmpty()) {
+ adapterDesc.Truncate(99);
+ }
+#endif
+
mozilla::glean::gfx_adapter_primary::description.Set(
NS_ConvertUTF16toUTF8(adapterDesc));
@@ -1335,7 +1343,7 @@ void gfxPlatform::ShutdownLayersIPC() {
if (XRE_IsContentProcess()) {
gfx::VRManagerChild::ShutDown();
- gfx::CanvasManagerChild::Shutdown();
+ gfx::CanvasShutdownManager::Shutdown();
// cf bug 1215265.
if (StaticPrefs::layers_child_process_shutdown()) {
layers::CompositorManagerChild::Shutdown();
@@ -1346,7 +1354,7 @@ void gfxPlatform::ShutdownLayersIPC() {
VideoBridgeParent::Shutdown();
RDDProcessManager::RDDProcessShutdown();
gfx::VRManagerChild::ShutDown();
- gfx::CanvasManagerChild::Shutdown();
+ gfx::CanvasShutdownManager::Shutdown();
layers::CompositorManagerChild::Shutdown();
layers::ImageBridgeChild::ShutDown();
// This could be running on either the Compositor thread, the Renderer
@@ -2273,7 +2281,7 @@ void gfxPlatform::FontsPrefsChanged(const char* aPref) {
!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
FlushFontAndWordCaches();
} else if (
-#if defined(XP_MACOSX)
+#if defined(XP_DARWIN)
!strcmp(GFX_PREF_CORETEXT_SHAPING, aPref) ||
#endif
!strcmp("gfx.font_rendering.ahem_antialias_none", aPref)) {
@@ -2693,7 +2701,7 @@ void gfxPlatform::InitWebRenderConfig() {
StaticPrefs::GetPrefName_gfx_webrender_batched_upload_threshold()));
if (WebRenderResourcePathOverride()) {
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationBool(
CrashReporter::Annotation::IsWebRenderResourcePathOverridden, true);
}
@@ -2740,7 +2748,7 @@ void gfxPlatform::InitWebRenderConfig() {
"FEATURE_FAILURE_WR_NO_GFX_INFO"_ns);
useVideoHwOverlay = false;
} else {
- if (status != nsIGfxInfo::FEATURE_ALLOW_ALWAYS) {
+ if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
FeatureState& feature =
gfxConfig::GetFeature(Feature::VIDEO_HARDWARE_OVERLAY);
feature.DisableByDefault(FeatureStatus::Blocked,
@@ -2897,6 +2905,49 @@ void gfxPlatform::InitWebRenderConfig() {
}
#endif
+ bool allowOverlayVpAutoHDR = false;
+ if (StaticPrefs::gfx_webrender_overlay_vp_auto_hdr_AtStartup()) {
+ allowOverlayVpAutoHDR = true;
+
+ nsCString failureId;
+ int32_t status;
+ const nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
+ if (NS_FAILED(gfxInfo->GetFeatureStatus(
+ nsIGfxInfo::FEATURE_OVERLAY_VP_AUTO_HDR, failureId, &status))) {
+ allowOverlayVpAutoHDR = false;
+ } else {
+ if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
+ allowOverlayVpAutoHDR = false;
+ }
+ }
+ }
+
+ if (allowOverlayVpAutoHDR) {
+ gfxVars::SetWebRenderOverlayVpAutoHDR(true);
+ }
+
+ bool allowOverlayVpSuperResolution = false;
+ if (StaticPrefs::gfx_webrender_overlay_vp_super_resolution_AtStartup()) {
+ allowOverlayVpSuperResolution = true;
+
+ nsCString failureId;
+ int32_t status;
+ const nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
+ if (NS_FAILED(gfxInfo->GetFeatureStatus(
+ nsIGfxInfo::FEATURE_OVERLAY_VP_SUPER_RESOLUTION, failureId,
+ &status))) {
+ allowOverlayVpSuperResolution = false;
+ } else {
+ if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
+ allowOverlayVpSuperResolution = false;
+ }
+ }
+ }
+
+ if (allowOverlayVpSuperResolution) {
+ gfxVars::SetWebRenderOverlayVpSuperResolution(true);
+ }
+
if (gfxConfig::IsEnabled(Feature::WEBRENDER_COMPOSITOR)) {
gfxVars::SetUseWebRenderCompositor(true);
}
diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp
index 709a0f3c27..bc0e123f85 100644
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -378,6 +378,40 @@ gfxPlatformFontList::~gfxPlatformFontList() {
NS_RELEASE(gFontListPrefObserver);
}
+void gfxPlatformFontList::GetMissingFonts(nsCString& aMissingFonts) {
+ AutoLock lock(mLock);
+
+ auto fontLists = GetFilteredPlatformFontLists();
+
+ if (!fontLists.Length()) {
+ aMissingFonts.Append("No font list available for this device.");
+ }
+
+ for (unsigned int i = 0; i < fontLists.Length(); i++) {
+ for (unsigned int j = 0; j < fontLists[i].second; j++) {
+ nsCString key(fontLists[i].first[j]);
+ GenerateFontListKey(key);
+
+ if (SharedFontList()) {
+ fontlist::Family* family = SharedFontList()->FindFamily(key);
+ if (!family) {
+ aMissingFonts.Append(fontLists[i].first[j]);
+ aMissingFonts.Append("|");
+ }
+ } else {
+ gfxFontFamily* familyEntry = mFontFamilies.GetWeak(key);
+ if (!familyEntry) {
+ familyEntry = mOtherFamilyNames.GetWeak(key);
+ }
+ if (!familyEntry) {
+ aMissingFonts.Append(fontLists[i].first[j]);
+ aMissingFonts.Append("|");
+ }
+ }
+ }
+ }
+}
+
/* static */
void gfxPlatformFontList::FontWhitelistPrefChanged(const char* aPref,
void* aClosure) {
@@ -700,6 +734,10 @@ void gfxPlatformFontList::GenerateFontListKey(const nsACString& aKeyName,
ToLowerCase(aResult);
}
+void gfxPlatformFontList::GenerateFontListKey(nsACString& aKeyName) {
+ ToLowerCase(aKeyName);
+}
+
// Used if a stylo thread wants to trigger InitOtherFamilyNames in the main
// process: we can't do IPC from the stylo thread so we post this to the main
// thread instead.
@@ -755,7 +793,7 @@ bool gfxPlatformFontList::InitOtherFamilyNames(
// (This is used so we can reliably run reftests that depend on localized
// font-family names being available.)
if (aDeferOtherFamilyNamesLoading &&
- StaticPrefs::gfx_font_loader_delay_AtStartup() > 0) {
+ StaticPrefs::gfx_font_loader_delay() > 0) {
if (!mPendingOtherFamilyNameTask) {
RefPtr<mozilla::CancelableRunnable> task =
new InitOtherFamilyNamesRunnable();
@@ -2648,7 +2686,7 @@ bool gfxPlatformFontList::LoadFontInfo() {
// Limit the time spent reading fonts in one pass, unless the font-loader
// delay was set to zero, in which case we run to completion even if it
// causes some jank.
- if (StaticPrefs::gfx_font_loader_delay_AtStartup() > 0) {
+ if (StaticPrefs::gfx_font_loader_delay() > 0) {
TimeDuration elapsed = TimeStamp::Now() - start;
if (elapsed.ToMilliseconds() > FONT_LOADER_MAX_TIMESLICE &&
i + 1 != endIndex) {
@@ -2751,7 +2789,7 @@ void gfxPlatformFontList::GetPrefsAndStartLoader() {
if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
return;
}
- uint32_t delay = std::max(1u, StaticPrefs::gfx_font_loader_delay_AtStartup());
+ uint32_t delay = std::max(1u, StaticPrefs::gfx_font_loader_delay());
if (NS_IsMainThread()) {
StartLoader(delay);
} else {
diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h
index 4d5b9e4015..3ab74c5f74 100644
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -245,6 +245,8 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
return sPlatformFontList;
}
+ void GetMissingFonts(nsCString& aMissingFonts);
+
static bool Initialize(gfxPlatformFontList* aList);
static void Shutdown() {
@@ -658,6 +660,9 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
mutable mozilla::RecursiveMutex mLock;
protected:
+ virtual nsTArray<std::pair<const char**, uint32_t>>
+ GetFilteredPlatformFontLists() = 0;
+
friend class mozilla::fontlist::FontList;
friend class InitOtherFamilyNamesForStylo;
@@ -867,7 +872,10 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// load the bad underline blocklist from pref.
void LoadBadUnderlineList();
+ // This version of the function will not modify aKeyName
void GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult);
+ // This version of the function WILL modify aKeyName
+ void GenerateFontListKey(nsACString& aKeyName);
virtual void GetFontFamilyNames(nsTArray<nsCString>& aFontFamilyNames)
MOZ_REQUIRES(mLock);
@@ -1010,13 +1018,14 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// When system-wide font lookup fails for a character, cache it to skip future
// searches. This is an array of bitsets, one for each FontVisibility level.
- mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count,
- gfxSparseBitSet>
+ mozilla::EnumeratedArray<FontVisibility, gfxSparseBitSet,
+ size_t(FontVisibility::Count)>
mCodepointsWithNoFonts MOZ_GUARDED_BY(mLock);
// the family to use for U+FFFD fallback, to avoid expensive search every time
// on pages with lots of problems
- mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count, FontFamily>
+ mozilla::EnumeratedArray<FontVisibility, FontFamily,
+ size_t(FontVisibility::Count)>
mReplacementCharFallbackFamily MOZ_GUARDED_BY(mLock);
// Sorted array of lowercased family names; use ContainsSorted to test
diff --git a/gfx/thebes/gfxPlatformMac.cpp b/gfx/thebes/gfxPlatformMac.cpp
index 02ec1a7b28..091b0dff28 100644
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -9,7 +9,6 @@
#include "mozilla/DataMutex.h"
#include "mozilla/gfx/2D.h"
-#include "gfxMacPlatformFontList.h"
#include "gfxMacFont.h"
#include "gfxCoreTextShaper.h"
#include "gfxTextRun.h"
@@ -20,7 +19,9 @@
#include "nsTArray.h"
#include "mozilla/Preferences.h"
#include "mozilla/VsyncDispatcher.h"
-#include "nsCocoaFeatures.h"
+#ifdef MOZ_WIDGET_COCOA
+# include "nsCocoaFeatures.h"
+#endif
#include "nsComponentManagerUtils.h"
#include "nsIFile.h"
#include "nsUnicodeProperties.h"
@@ -48,6 +49,14 @@ using namespace mozilla::unicode;
using mozilla::dom::SystemFontList;
+#ifdef MOZ_WIDGET_COCOA
+# include "gfxMacPlatformFontList.h"
+using PlatformFontListClass = gfxMacPlatformFontList;
+#else
+# include "IOSPlatformFontList.h"
+using PlatformFontListClass = IOSPlatformFontList;
+#endif
+
// A bunch of fonts for "additional language support" are shipped in a
// "Language Support" directory, and don't show up in the standard font
// list returned by CTFontManagerCopyAvailableFontFamilyNames unless
@@ -62,7 +71,7 @@ void gfxPlatformMac::FontRegistrationCallback(void* aUnused) {
PR_SetCurrentThreadName("RegisterFonts");
for (const auto& dir : kLangFontsDirs) {
- gfxMacPlatformFontList::ActivateFontsFromDir(dir);
+ PlatformFontListClass::ActivateFontsFromDir(dir);
}
}
@@ -111,11 +120,11 @@ BackendPrefsData gfxPlatformMac::GetBackendPrefs() const {
}
bool gfxPlatformMac::CreatePlatformFontList() {
- return gfxPlatformFontList::Initialize(new gfxMacPlatformFontList);
+ return gfxPlatformFontList::Initialize(new PlatformFontListClass);
}
void gfxPlatformMac::ReadSystemFontList(SystemFontList* aFontList) {
- gfxMacPlatformFontList::PlatformFontList()->ReadSystemFontList(aFontList);
+ PlatformFontListClass::PlatformFontList()->ReadSystemFontList(aFontList);
}
already_AddRefed<gfxASurface> gfxPlatformMac::CreateOffscreenSurface(
@@ -668,8 +677,8 @@ void gfxPlatformMac::GetCommonFallbackFonts(uint32_t aCh, Script aRunScript,
void gfxPlatformMac::LookupSystemFont(
mozilla::LookAndFeel::FontID aSystemFontID, nsACString& aSystemFontName,
gfxFontStyle& aFontStyle) {
- return gfxMacPlatformFontList::LookupSystemFont(aSystemFontID,
- aSystemFontName, aFontStyle);
+ return PlatformFontListClass::LookupSystemFont(aSystemFontID, aSystemFontName,
+ aFontStyle);
}
uint32_t gfxPlatformMac::ReadAntiAliasingThreshold() {
@@ -700,6 +709,7 @@ uint32_t gfxPlatformMac::ReadAntiAliasingThreshold() {
bool gfxPlatformMac::AccelerateLayersByDefault() { return true; }
+#ifdef MOZ_WIDGET_COCOA
// This is the renderer output callback function, called on the vsync thread
static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
const CVTimeStamp* aNow,
@@ -934,9 +944,11 @@ static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
vsyncSource->NotifyVsync(previousVsync, outputTime);
return kCVReturnSuccess;
}
+#endif
already_AddRefed<mozilla::gfx::VsyncSource>
gfxPlatformMac::CreateGlobalHardwareVsyncSource() {
+#ifdef MOZ_WIDGET_COCOA
RefPtr<VsyncSource> osxVsyncSource = new OSXVsyncSource();
osxVsyncSource->EnableVsync();
if (!osxVsyncSource->IsVsyncEnabled()) {
@@ -947,6 +959,10 @@ gfxPlatformMac::CreateGlobalHardwareVsyncSource() {
osxVsyncSource->DisableVsync();
return osxVsyncSource.forget();
+#else
+ // TODO: CADisplayLink
+ return GetSoftwareVsyncSource();
+#endif
}
bool gfxPlatformMac::SupportsHDR() {
@@ -958,8 +974,10 @@ bool gfxPlatformMac::SupportsHDR() {
return false;
}
+#ifdef MOZ_WIDGET_UIKIT
+ return false;
+#elif defined(EARLY_BETA_OR_EARLIER)
// Screen is capable. Is the OS capable?
-#ifdef EARLY_BETA_OR_EARLIER
// More-or-less supported in Catalina.
return true;
#else
@@ -974,7 +992,10 @@ nsTArray<uint8_t> gfxPlatformMac::GetPlatformCMSOutputProfileData() {
return prefProfileData;
}
- CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
+ CGColorSpaceRef cspace = nil;
+#ifdef MOZ_WIDGET_COCOA
+ cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
+#endif
if (!cspace) {
cspace = ::CGColorSpaceCreateDeviceRGB();
}
diff --git a/gfx/thebes/gfxQuartzSurface.h b/gfx/thebes/gfxQuartzSurface.h
index fbc081197b..cb5e54c80b 100644
--- a/gfx/thebes/gfxQuartzSurface.h
+++ b/gfx/thebes/gfxQuartzSurface.h
@@ -10,7 +10,11 @@
#include "nsSize.h"
#include "gfxPoint.h"
-#include <Carbon/Carbon.h>
+#ifdef MOZ_WIDGET_COCOA
+# include <Carbon/Carbon.h>
+#else
+# include <CoreGraphics/CoreGraphics.h>
+#endif
class gfxContext;
class gfxImageSurface;
diff --git a/gfx/thebes/gfxUserFontSet.cpp b/gfx/thebes/gfxUserFontSet.cpp
index aeaf296200..e9a2f513b3 100644
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -492,38 +492,54 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aIsContinue) {
else if (currSrc.mSourceType == gfxFontFaceSrc::eSourceType_URL) {
if (gfxPlatform::GetPlatform()->IsFontFormatSupported(
currSrc.mFormatHint, currSrc.mTechFlags)) {
- if (ServoStyleSet* set = gfxFontUtils::CurrentServoStyleSet()) {
- // Only support style worker threads synchronously getting
- // entries from the font cache when it's not a data: URI
- // @font-face that came from UA or user sheets, since we
- // were not able to call IsFontLoadAllowed ahead of time
- // for these entries.
- if (currSrc.mUseOriginPrincipal && IgnorePrincipal(currSrc.mURI)) {
- set->AppendTask(PostTraversalTask::LoadFontEntry(this));
- SetLoadState(STATUS_LOAD_PENDING);
- return;
+ // TODO(emilio): Make UserFontCache thread-safe maybe? But we need to
+ // potentially do CSP checks so maybe not trivial.
+ const bool canCheckCache = [&] {
+ if (NS_IsMainThread()) {
+ return true;
}
- }
+ if (gfxFontUtils::CurrentServoStyleSet()) {
+ // Only support style worker threads synchronously getting entries
+ // from the font cache when it's not a data: URI @font-face that
+ // came from UA or user sheets, since we were not able to call
+ // IsFontLoadAllowed ahead of time for these entries.
+ return !currSrc.mUseOriginPrincipal ||
+ !IgnorePrincipal(currSrc.mURI);
+ }
+ return false;
+ }();
// see if we have an existing entry for this source
- gfxFontEntry* fe =
- gfxUserFontSet::UserFontCache::GetFont(currSrc, *this);
- if (fe) {
- mPlatformFontEntry = fe;
- SetLoadState(STATUS_LOADED);
- LOG(
- ("userfonts (%p) [src %d] "
- "loaded uri from cache: (%s) for (%s)\n",
- fontSet.get(), mCurrentSrcIndex,
- currSrc.mURI->GetSpecOrDefault().get(), mFamilyName.get()));
- return;
+ if (canCheckCache) {
+ gfxFontEntry* fe =
+ gfxUserFontSet::UserFontCache::GetFont(currSrc, *this);
+ if (fe) {
+ mPlatformFontEntry = fe;
+ SetLoadState(STATUS_LOADED);
+ LOG(
+ ("userfonts (%p) [src %d] "
+ "loaded uri from cache: (%s) for (%s)\n",
+ fontSet.get(), mCurrentSrcIndex,
+ currSrc.mURI->GetSpecOrDefault().get(), mFamilyName.get()));
+ return;
+ }
}
if (ServoStyleSet* set = gfxFontUtils::CurrentServoStyleSet()) {
// If we need to start a font load and we're on a style
// worker thread, we have to defer it.
+ SetLoadState(STATUS_LOAD_PENDING);
set->AppendTask(PostTraversalTask::LoadFontEntry(this));
+ return;
+ }
+
+ if (dom::IsCurrentThreadRunningWorker()) {
+ // TODO: Maybe support loading the font entry in workers, at least for
+ // buffers or other sync sources?
SetLoadState(STATUS_LOAD_PENDING);
+ NS_DispatchToMainThread(
+ NewRunnableMethod("gfxUserFontEntry::ContinueLoad", this,
+ &gfxUserFontEntry::ContinueLoad));
return;
}
@@ -551,9 +567,9 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aIsContinue) {
fontSet->LogMessage(this, mCurrentSrcIndex, "font load failed",
nsIScriptError::errorFlag, rv);
} else if (!aIsContinue) {
- RefPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
- "gfxUserFontSet::AsyncContinueLoad",
- [loader = RefPtr{this}] { loader->ContinueLoad(); });
+ RefPtr<nsIRunnable> runnable =
+ NewRunnableMethod("gfxUserFontEntry::ContinueLoad", this,
+ &gfxUserFontEntry::ContinueLoad);
SetLoadState(STATUS_LOAD_PENDING);
// We don't want to trigger the channel open at random points in
// time, because it can run privileged JS.
@@ -817,13 +833,6 @@ void gfxUserFontEntry::Load() {
if (mUserFontLoadState != STATUS_NOT_LOADED) {
return;
}
- if (dom::IsCurrentThreadRunningWorker()) {
- // TODO: Maybe support loading the font entry in workers, at least for
- // buffers or other sync sources?
- NS_DispatchToMainThread(NewRunnableMethod("gfxUserFontEntry::Load", this,
- &gfxUserFontEntry::Load));
- return;
- }
LoadNextSrc();
}
diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp
index e6994f8665..93de20f445 100644
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -540,42 +540,38 @@ void gfxWindowsPlatform::UpdateSupportsHDR() {
return;
}
- // Set mSupportsHDR to true if any of the DeviceManager outputs have both:
- // 1) greater than 8-bit color
- // 2) a colorspace that uses BT2020
+ // Set mSupportsHDR to true if any of the DeviceManager outputs have a BT2020
+ // colorspace with EOTF2084 gamma curve, this indicates the system is sending
+ // an HDR format to at least one monitor. The colorspace returned by DXGI is
+ // very vague - we only see DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 for HDR
+ // and DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 for SDR modes, even if the
+ // monitor is using something like YCbCr444 according to Settings
+ // (System -> Display Settings -> Advanced Display). To get more specific
+ // info we would need to query the DISPLAYCONFIG values in WinGDI.
+ //
+ // Note that the bit depth used to be checked here, but as of Windows 11 22H2,
+ // HDR is supported with 8bpc for lower bandwidth, where DWM converts to
+ // dithered RGB8 rather than RGB10, which doesn't really matter here.
+ //
+ // This only returns true if there is an HDR display connected at app start,
+ // if the user switches to HDR to watch a video, we won't know that here, and
+ // if no displays are connected we return false (e.g. if Windows Update
+ // restarted a laptop with its lid closed and no external displays, we will
+ // see zero outputs here when the app is restarted automatically).
+ //
+ // It would be better to track if HDR is ever used and report that telemetry
+ // so we know if HDR matters, not just when it is detected at app start.
+ //
+ // Further reading:
+ // https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range
+ // https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-displayconfig_sdr_white_level
DeviceManagerDx* dx = DeviceManagerDx::Get();
nsTArray<DXGI_OUTPUT_DESC1> outputs = dx->EnumerateOutputs();
for (auto& output : outputs) {
- if (output.BitsPerColor <= 8) {
- continue;
- }
-
- switch (output.ColorSpace) {
- case DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020:
- case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020:
- case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020:
- case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020:
- case DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020:
- case DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020:
- case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020:
- case DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020:
- case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020:
- case DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020:
- case DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020:
-#ifndef __MINGW32__
- // Windows MinGW has an older dxgicommon.h that doesn't define
- // these enums. We'd like to define them ourselves in that case,
- // but there's no compilable way to add new enums to an existing
- // enum type. So instead we just don't check for these values.
- case DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020:
- case DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020:
- case DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020:
-#endif
- mSupportsHDR = true;
- return;
- default:
- break;
+ if (output.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
+ mSupportsHDR = true;
+ return;
}
}
diff --git a/gfx/thebes/moz.build b/gfx/thebes/moz.build
index fd1fcf236d..3d99906827 100644
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -96,16 +96,13 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "android":
"gfxFT2Utils.cpp",
"PrintTargetPDF.cpp",
]
-elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
EXPORTS += [
"gfxMacUtils.h",
"gfxPlatformMac.h",
"gfxQuartzNativeDrawing.h",
"gfxQuartzSurface.h",
]
- EXPORTS.mozilla.gfx += [
- "PrintTargetCG.h",
- ]
SOURCES += [
"CoreTextFontList.cpp",
"gfxCoreTextShaper.cpp",
@@ -114,8 +111,14 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
"gfxPlatformMac.cpp",
"gfxQuartzNativeDrawing.cpp",
"gfxQuartzSurface.cpp",
- "PrintTargetCG.mm",
]
+ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+ EXPORTS.mozilla.gfx += [
+ "PrintTargetCG.h",
+ ]
+ SOURCES += [
+ "PrintTargetCG.mm",
+ ]
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
EXPORTS += [
"gfxFT2FontBase.h",
@@ -239,6 +242,10 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
UNIFIED_SOURCES += [
"gfxMacPlatformFontList.mm",
]
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "uikit":
+ UNIFIED_SOURCES += [
+ "IOSPlatformFontList.mm",
+ ]
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
UNIFIED_SOURCES += [
"D3D11Checks.cpp",
diff --git a/gfx/vr/ipc/VRProcessManager.cpp b/gfx/vr/ipc/VRProcessManager.cpp
index f3bc13bac0..440d50546c 100644
--- a/gfx/vr/ipc/VRProcessManager.cpp
+++ b/gfx/vr/ipc/VRProcessManager.cpp
@@ -87,8 +87,8 @@ void VRProcessManager::DestroyProcess() {
mProcess = nullptr;
mVRChild = nullptr;
- CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::VRProcessStatus,
- "Destroyed"_ns);
+ CrashReporter::RecordAnnotationCString(
+ CrashReporter::Annotation::VRProcessStatus, "Destroyed");
}
bool VRProcessManager::EnsureVRReady() {
@@ -134,8 +134,8 @@ void VRProcessManager::OnProcessLaunchComplete(VRProcessParent* aParent) {
}
mQueuedPrefs.Clear();
- CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::VRProcessStatus,
- "Running"_ns);
+ CrashReporter::RecordAnnotationCString(
+ CrashReporter::Annotation::VRProcessStatus, "Running");
}
void VRProcessManager::OnProcessUnexpectedShutdown(VRProcessParent* aParent) {
diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml
index f6b3fd637f..0f0c069e87 100644
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -33,7 +33,7 @@ features = ["capture", "serialize_program", "gecko", "sw_compositor"]
dwrote = "0.11"
winapi = "0.3"
-[target.'cfg(target_os = "macos")'.dependencies]
+[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
core-foundation = "0.9"
core-graphics = "0.23"
foreign-types = "0.5.0"
diff --git a/gfx/webrender_bindings/DCLayerTree.cpp b/gfx/webrender_bindings/DCLayerTree.cpp
index eee5601182..177979a466 100644
--- a/gfx/webrender_bindings/DCLayerTree.cpp
+++ b/gfx/webrender_bindings/DCLayerTree.cpp
@@ -1178,6 +1178,126 @@ void DCSurfaceVideo::AttachExternalImage(wr::ExternalImageId aExternalImage) {
mRenderTextureHost = texture;
}
+static UINT GetVendorId(ID3D11VideoDevice* const aVideoDevice) {
+ RefPtr<IDXGIDevice> dxgiDevice;
+ RefPtr<IDXGIAdapter> adapter;
+ aVideoDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(dxgiDevice));
+ dxgiDevice->GetAdapter(getter_AddRefs(adapter));
+
+ DXGI_ADAPTER_DESC adapterDesc;
+ adapter->GetDesc(&adapterDesc);
+
+ return adapterDesc.VendorId;
+}
+
+static HRESULT SetNvidiaVpSuperResolution(ID3D11VideoContext* aVideoContext,
+ ID3D11VideoProcessor* aVideoProcessor,
+ bool aEnable) {
+ LOG("SetNvidiaVpSuperResolution() aEnable=%d", aEnable);
+
+ // Undocumented NVIDIA driver constants
+ constexpr GUID nvGUID = {0xD43CE1B3,
+ 0x1F4B,
+ 0x48AC,
+ {0xBA, 0xEE, 0xC3, 0xC2, 0x53, 0x75, 0xE6, 0xF7}};
+
+ constexpr UINT nvExtensionVersion = 0x1;
+ constexpr UINT nvExtensionMethodSuperResolution = 0x2;
+ struct {
+ UINT version;
+ UINT method;
+ UINT enable;
+ } streamExtensionInfo = {nvExtensionVersion, nvExtensionMethodSuperResolution,
+ aEnable ? 1u : 0};
+
+ HRESULT hr;
+ hr = aVideoContext->VideoProcessorSetStreamExtension(
+ aVideoProcessor, 0, &nvGUID, sizeof(streamExtensionInfo),
+ &streamExtensionInfo);
+ return hr;
+}
+
+static HRESULT SetVpSuperResolution(UINT aGpuVendorId,
+ ID3D11VideoContext* aVideoContext,
+ ID3D11VideoProcessor* aVideoProcessor,
+ bool aEnable) {
+ MOZ_ASSERT(aVideoContext);
+ MOZ_ASSERT(aVideoProcessor);
+
+ if (aGpuVendorId == 0x10DE) {
+ return SetNvidiaVpSuperResolution(aVideoContext, aVideoProcessor, aEnable);
+ }
+ return E_NOTIMPL;
+}
+
+static bool GetNvidiaRTXVideoTrueHDRSupported(
+ ID3D11VideoContext* aVideoContext, ID3D11VideoProcessor* aVideoProcessor) {
+ const GUID kNvidiaTrueHDRInterfaceGUID = {
+ 0xfdd62bb4,
+ 0x620b,
+ 0x4fd7,
+ {0x9a, 0xb3, 0x1e, 0x59, 0xd0, 0xd5, 0x44, 0xb3}};
+ UINT available = 0;
+ HRESULT hr = aVideoContext->VideoProcessorGetStreamExtension(
+ aVideoProcessor, 0, &kNvidiaTrueHDRInterfaceGUID, sizeof(available),
+ &available);
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ bool driverSupportsTrueHdr = (available == 1);
+ return driverSupportsTrueHdr;
+}
+
+static HRESULT SetNvidiaRTXVideoTrueHDR(ID3D11VideoContext* aVideoContext,
+ ID3D11VideoProcessor* aVideoProcessor,
+ bool aEnable) {
+ constexpr GUID kNvidiaTrueHDRInterfaceGUID = {
+ 0xfdd62bb4,
+ 0x620b,
+ 0x4fd7,
+ {0x9a, 0xb3, 0x1e, 0x59, 0xd0, 0xd5, 0x44, 0xb3}};
+ constexpr UINT kStreamExtensionMethodTrueHDR = 0x3;
+ const UINT TrueHDRVersion4 = 4;
+ struct {
+ UINT version;
+ UINT method;
+ UINT enable : 1;
+ UINT reserved : 31;
+ } streamExtensionInfo = {TrueHDRVersion4, kStreamExtensionMethodTrueHDR,
+ aEnable ? 1u : 0u, 0u};
+ HRESULT hr = aVideoContext->VideoProcessorSetStreamExtension(
+ aVideoProcessor, 0, &kNvidiaTrueHDRInterfaceGUID,
+ sizeof(streamExtensionInfo), &streamExtensionInfo);
+ return hr;
+}
+
+static bool GetVpAutoHDRSupported(UINT aGpuVendorId,
+ ID3D11VideoContext* aVideoContext,
+ ID3D11VideoProcessor* aVideoProcessor) {
+ MOZ_ASSERT(aVideoContext);
+ MOZ_ASSERT(aVideoProcessor);
+
+ if (aGpuVendorId == 0x10DE) {
+ return GetNvidiaRTXVideoTrueHDRSupported(aVideoContext, aVideoProcessor);
+ }
+ return false;
+}
+
+static HRESULT SetVpAutoHDR(UINT aGpuVendorId,
+ ID3D11VideoContext* aVideoContext,
+ ID3D11VideoProcessor* aVideoProcessor,
+ bool aEnable) {
+ MOZ_ASSERT(aVideoContext);
+ MOZ_ASSERT(aVideoProcessor);
+
+ if (aGpuVendorId == 0x10DE) {
+ return SetNvidiaRTXVideoTrueHDR(aVideoContext, aVideoProcessor, aEnable);
+ }
+ MOZ_ASSERT_UNREACHABLE("Unexpected to be called");
+ return E_NOTIMPL;
+}
+
bool DCSurfaceVideo::CalculateSwapChainSize(gfx::Matrix& aTransform) {
if (!mRenderTextureHost) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
@@ -1225,18 +1345,39 @@ bool DCSurfaceVideo::CalculateSwapChainSize(gfx::Matrix& aTransform) {
transform = gfx::Matrix::Translation(aTransform.GetTranslation());
}
- if (!mVideoSwapChain || mSwapChainSize != swapChainSize || mIsDRM != isDRM) {
+ if (!mDCLayerTree->EnsureVideoProcessor(mVideoSize, swapChainSize)) {
+ gfxCriticalNote << "EnsureVideoProcessor Failed";
+ return false;
+ }
+
+ MOZ_ASSERT(mDCLayerTree->GetVideoContext());
+ MOZ_ASSERT(mDCLayerTree->GetVideoProcessor());
+
+ const UINT vendorId = GetVendorId(mDCLayerTree->GetVideoDevice());
+ const bool driverSupportsTrueHDR =
+ GetVpAutoHDRSupported(vendorId, mDCLayerTree->GetVideoContext(),
+ mDCLayerTree->GetVideoProcessor());
+ const bool contentIsHDR = false; // XXX for now, only non-HDR is supported.
+ const bool monitorIsHDR = gfx::DeviceManagerDx::Get()->SystemHDREnabled();
+ const bool powerIsCharging = RenderThread::Get()->GetPowerIsCharging();
+
+ bool useVpAutoHDR = gfx::gfxVars::WebRenderOverlayVpAutoHDR() &&
+ !contentIsHDR && monitorIsHDR && driverSupportsTrueHDR &&
+ powerIsCharging && !mVpAutoHDRFailed;
+
+ if (!mVideoSwapChain || mSwapChainSize != swapChainSize || mIsDRM != isDRM ||
+ mUseVpAutoHDR != useVpAutoHDR) {
needsToPresent = true;
ReleaseDecodeSwapChainResources();
// Update mSwapChainSize before creating SwapChain
mSwapChainSize = swapChainSize;
mIsDRM = isDRM;
- auto swapChainFormat = GetSwapChainFormat();
+ auto swapChainFormat = GetSwapChainFormat(useVpAutoHDR);
bool useYUVSwapChain = IsYUVSwapChainFormat(swapChainFormat);
if (useYUVSwapChain) {
// Tries to create YUV SwapChain
- CreateVideoSwapChain();
+ CreateVideoSwapChain(swapChainFormat);
if (!mVideoSwapChain) {
mFailedYuvSwapChain = true;
ReleaseDecodeSwapChainResources();
@@ -1246,11 +1387,21 @@ bool DCSurfaceVideo::CalculateSwapChainSize(gfx::Matrix& aTransform) {
}
// Tries to create RGB SwapChain
if (!mVideoSwapChain) {
- CreateVideoSwapChain();
+ CreateVideoSwapChain(swapChainFormat);
+ }
+ if (!mVideoSwapChain && useVpAutoHDR) {
+ mVpAutoHDRFailed = true;
+ gfxCriticalNoteOnce << "Failed to create video SwapChain for VpAutoHDR";
+
+ // Disable VpAutoHDR
+ useVpAutoHDR = false;
+ swapChainFormat = GetSwapChainFormat(useVpAutoHDR);
+ CreateVideoSwapChain(swapChainFormat);
}
}
aTransform = transform;
+ mUseVpAutoHDR = useVpAutoHDR;
return needsToPresent;
}
@@ -1270,8 +1421,7 @@ void DCSurfaceVideo::PresentVideo() {
mVisual->SetContent(mVideoSwapChain);
if (!CallVideoProcessorBlt()) {
- auto swapChainFormat = GetSwapChainFormat();
- bool useYUVSwapChain = IsYUVSwapChainFormat(swapChainFormat);
+ bool useYUVSwapChain = IsYUVSwapChainFormat(mSwapChainFormat);
if (useYUVSwapChain) {
mFailedYuvSwapChain = true;
ReleaseDecodeSwapChainResources();
@@ -1392,14 +1542,17 @@ void DCSurfaceVideo::PresentVideo() {
}
}
-DXGI_FORMAT DCSurfaceVideo::GetSwapChainFormat() {
+DXGI_FORMAT DCSurfaceVideo::GetSwapChainFormat(bool aUseVpAutoHDR) {
+ if (aUseVpAutoHDR) {
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ }
if (mFailedYuvSwapChain || !mDCLayerTree->SupportsHardwareOverlays()) {
return DXGI_FORMAT_B8G8R8A8_UNORM;
}
return mDCLayerTree->GetOverlayFormatForSDR();
}
-bool DCSurfaceVideo::CreateVideoSwapChain() {
+bool DCSurfaceVideo::CreateVideoSwapChain(DXGI_FORMAT aSwapChainFormat) {
MOZ_ASSERT(mRenderTextureHost);
mFirstPresent = true;
@@ -1423,12 +1576,10 @@ bool DCSurfaceVideo::CreateVideoSwapChain() {
return false;
}
- auto swapChainFormat = GetSwapChainFormat();
-
DXGI_SWAP_CHAIN_DESC1 desc = {};
desc.Width = mSwapChainSize.width;
desc.Height = mSwapChainSize.height;
- desc.Format = swapChainFormat;
+ desc.Format = aSwapChainFormat;
desc.Stereo = FALSE;
desc.SampleDesc.Count = 1;
desc.BufferCount = mSwapChainBufferCount;
@@ -1436,7 +1587,7 @@ bool DCSurfaceVideo::CreateVideoSwapChain() {
desc.Scaling = DXGI_SCALING_STRETCH;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.Flags = DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO;
- if (IsYUVSwapChainFormat(swapChainFormat)) {
+ if (IsYUVSwapChainFormat(aSwapChainFormat)) {
desc.Flags |= DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO;
}
if (mIsDRM) {
@@ -1455,7 +1606,7 @@ bool DCSurfaceVideo::CreateVideoSwapChain() {
return false;
}
- mSwapChainFormat = swapChainFormat;
+ mSwapChainFormat = aSwapChainFormat;
return true;
}
@@ -1494,50 +1645,6 @@ static Maybe<DXGI_COLOR_SPACE_TYPE> GetSourceDXGIColorSpace(
return GetSourceDXGIColorSpace(info.space, info.range);
}
-static void SetNvidiaVideoSuperRes(ID3D11VideoContext* videoContext,
- ID3D11VideoProcessor* videoProcessor,
- bool enabled) {
- LOG("SetNvidiaVideoSuperRes() enabled=%d", enabled);
-
- // Undocumented NVIDIA driver constants
- constexpr GUID nvGUID = {0xD43CE1B3,
- 0x1F4B,
- 0x48AC,
- {0xBA, 0xEE, 0xC3, 0xC2, 0x53, 0x75, 0xE6, 0xF7}};
-
- constexpr UINT nvExtensionVersion = 0x1;
- constexpr UINT nvExtensionMethodSuperResolution = 0x2;
- struct {
- UINT version;
- UINT method;
- UINT enable;
- } streamExtensionInfo = {nvExtensionVersion, nvExtensionMethodSuperResolution,
- enabled ? 1u : 0};
-
- HRESULT hr;
- hr = videoContext->VideoProcessorSetStreamExtension(
- videoProcessor, 0, &nvGUID, sizeof(streamExtensionInfo),
- &streamExtensionInfo);
-
- // Ignore errors as could be unsupported
- if (FAILED(hr)) {
- LOG("SetNvidiaVideoSuperRes() error: %lx", hr);
- return;
- }
-}
-
-static UINT GetVendorId(ID3D11VideoDevice* const videoDevice) {
- RefPtr<IDXGIDevice> dxgiDevice;
- RefPtr<IDXGIAdapter> adapter;
- videoDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(dxgiDevice));
- dxgiDevice->GetAdapter(getter_AddRefs(adapter));
-
- DXGI_ADAPTER_DESC adapterDesc;
- adapter->GetDesc(&adapterDesc);
-
- return adapterDesc.VendorId;
-}
-
bool DCSurfaceVideo::CallVideoProcessorBlt() {
MOZ_ASSERT(mRenderTextureHost);
@@ -1576,11 +1683,6 @@ bool DCSurfaceVideo::CallVideoProcessorBlt() {
}
}
- if (!mDCLayerTree->EnsureVideoProcessor(mVideoSize, mSwapChainSize)) {
- gfxCriticalNote << "EnsureVideoProcessor Failed";
- return false;
- }
-
RefPtr<IDXGISwapChain3> swapChain3;
mVideoSwapChain->QueryInterface(
(IDXGISwapChain3**)getter_AddRefs(swapChain3));
@@ -1609,6 +1711,13 @@ bool DCSurfaceVideo::CallVideoProcessorBlt() {
IsYUVSwapChainFormat(mSwapChainFormat)
? inputColorSpace
: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
+
+ if (mUseVpAutoHDR) {
+ outputColorSpace = mSwapChainFormat == DXGI_FORMAT_R16G16B16A16_FLOAT
+ ? DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
+ : DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
+ }
+
hr = swapChain3->SetColorSpace1(outputColorSpace);
if (FAILED(hr)) {
gfxCriticalNoteOnce << "SetColorSpace1 failed: " << gfx::hexa(hr);
@@ -1679,9 +1788,24 @@ bool DCSurfaceVideo::CallVideoProcessorBlt() {
}
const UINT vendorId = GetVendorId(videoDevice);
- if (vendorId == 0x10DE &&
- StaticPrefs::gfx_webrender_super_resolution_nvidia_AtStartup()) {
- SetNvidiaVideoSuperRes(videoContext, videoProcessor, true);
+ const auto powerIsCharging = RenderThread::Get()->GetPowerIsCharging();
+ if (gfx::gfxVars::WebRenderOverlayVpSuperResolution() &&
+ !mVpSuperResolutionFailed && powerIsCharging) {
+ hr = SetVpSuperResolution(vendorId, videoContext, videoProcessor, true);
+ if (FAILED(hr)) {
+ if (hr != E_NOTIMPL) {
+ gfxCriticalNoteOnce << "SetVpSuperResolution failed: " << gfx::hexa(hr);
+ }
+ mVpSuperResolutionFailed = true;
+ }
+ }
+
+ if (mUseVpAutoHDR) {
+ hr = SetVpAutoHDR(vendorId, videoContext, videoProcessor, true);
+ if (FAILED(hr)) {
+ gfxCriticalNoteOnce << "SetVpAutoHDR failed: " << gfx::hexa(hr);
+ mVpAutoHDRFailed = true;
+ }
}
hr = videoContext->VideoProcessorBlt(videoProcessor, mOutputView, 0, 1,
@@ -1703,6 +1827,7 @@ void DCSurfaceVideo::ReleaseDecodeSwapChainResources() {
::CloseHandle(mSwapChainSurfaceHandle);
mSwapChainSurfaceHandle = 0;
}
+ mUseVpAutoHDR = false;
}
DCSurfaceHandle::DCSurfaceHandle(bool aIsOpaque, DCLayerTree* aDCLayerTree)
diff --git a/gfx/webrender_bindings/DCLayerTree.h b/gfx/webrender_bindings/DCLayerTree.h
index babd1112fb..6d3a611802 100644
--- a/gfx/webrender_bindings/DCLayerTree.h
+++ b/gfx/webrender_bindings/DCLayerTree.h
@@ -389,8 +389,8 @@ class DCSurfaceVideo : public DCSurface {
protected:
virtual ~DCSurfaceVideo();
- DXGI_FORMAT GetSwapChainFormat();
- bool CreateVideoSwapChain();
+ DXGI_FORMAT GetSwapChainFormat(bool aUseVpAutoHDR);
+ bool CreateVideoSwapChain(DXGI_FORMAT aFormat);
bool CallVideoProcessorBlt();
void ReleaseDecodeSwapChainResources();
@@ -409,6 +409,9 @@ class DCSurfaceVideo : public DCSurface {
int mSlowPresentCount = 0;
bool mFirstPresent = true;
const UINT mSwapChainBufferCount;
+ bool mUseVpAutoHDR = false;
+ bool mVpAutoHDRFailed = false;
+ bool mVpSuperResolutionFailed = false;
};
/**
diff --git a/gfx/webrender_bindings/RenderCompositor.cpp b/gfx/webrender_bindings/RenderCompositor.cpp
index 8dd6e8ff00..1712eca855 100644
--- a/gfx/webrender_bindings/RenderCompositor.cpp
+++ b/gfx/webrender_bindings/RenderCompositor.cpp
@@ -31,7 +31,7 @@
# include "mozilla/webrender/RenderCompositorNative.h"
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
# include "mozilla/webrender/RenderCompositorNative.h"
#endif
@@ -168,7 +168,7 @@ void wr_partial_present_compositor_set_buffer_damage_region(
UniquePtr<RenderCompositor> RenderCompositor::Create(
const RefPtr<widget::CompositorWidget>& aWidget, nsACString& aError) {
if (aWidget->GetCompositorOptions().UseSoftwareWebRender()) {
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
// Mac uses NativeLayerCA
if (!gfxPlatform::IsHeadless()) {
return RenderCompositorNativeSWGL::Create(aWidget, aError);
@@ -216,7 +216,7 @@ UniquePtr<RenderCompositor> RenderCompositor::Create(
#if defined(MOZ_WIDGET_ANDROID)
// RenderCompositorOGL is not used on android
return nullptr;
-#elif defined(XP_MACOSX)
+#elif defined(XP_DARWIN)
// Mac uses NativeLayerCA
return RenderCompositorNativeOGL::Create(aWidget, aError);
#else
diff --git a/gfx/webrender_bindings/RenderCompositorNative.cpp b/gfx/webrender_bindings/RenderCompositorNative.cpp
index 81cafd1fd6..3b5a29948e 100644
--- a/gfx/webrender_bindings/RenderCompositorNative.cpp
+++ b/gfx/webrender_bindings/RenderCompositorNative.cpp
@@ -31,7 +31,7 @@ RenderCompositorNative::RenderCompositorNative(
mNativeLayerRoot(GetWidget()->GetNativeLayerRoot()) {
LOG("RenderCompositorNative::RenderCompositorNative()");
-#if defined(XP_MACOSX) || defined(MOZ_WAYLAND)
+#if defined(XP_DARWIN) || defined(MOZ_WAYLAND)
auto pool = RenderThread::Get()->SharedSurfacePool();
if (pool) {
mSurfacePoolHandle = pool->GetHandleForGL(aGL);
@@ -103,7 +103,7 @@ bool RenderCompositorNative::Resume() { return true; }
inline layers::WebRenderCompositor RenderCompositorNative::CompositorType()
const {
if (gfx::gfxVars::UseWebRenderCompositor()) {
-#if defined(XP_MACOSX)
+#if defined(XP_DARWIN)
return layers::WebRenderCompositor::CORE_ANIMATION;
#elif defined(MOZ_WAYLAND)
return layers::WebRenderCompositor::WAYLAND;
@@ -123,7 +123,7 @@ bool RenderCompositorNative::ShouldUseNativeCompositor() {
void RenderCompositorNative::GetCompositorCapabilities(
CompositorCapabilities* aCaps) {
RenderCompositor::GetCompositorCapabilities(aCaps);
-#if defined(XP_MACOSX)
+#if defined(XP_DARWIN)
aCaps->supports_surface_for_backdrop = !gfx::gfxVars::UseSoftwareWebRender();
#endif
}
@@ -509,7 +509,7 @@ void RenderCompositorNativeOGL::DoSwap() {
void RenderCompositorNativeOGL::DoFlush() { mGL->fFlush(); }
void RenderCompositorNativeOGL::InsertFrameDoneSync() {
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
// Only do this on macOS.
// On other platforms, SwapBuffers automatically applies back-pressure.
if (mThisFrameDoneSync) {
diff --git a/gfx/webrender_bindings/RenderMacIOSurfaceTextureHost.cpp b/gfx/webrender_bindings/RenderMacIOSurfaceTextureHost.cpp
index bb0575949b..c1f93327e5 100644
--- a/gfx/webrender_bindings/RenderMacIOSurfaceTextureHost.cpp
+++ b/gfx/webrender_bindings/RenderMacIOSurfaceTextureHost.cpp
@@ -6,16 +6,20 @@
#include "RenderMacIOSurfaceTextureHost.h"
-#include "GLContextCGL.h"
+#ifdef XP_MACOSX
+# include "GLContextCGL.h"
+#else
+# include "GLContextEAGL.h"
+#endif
+
#include "mozilla/gfx/Logging.h"
#include "ScopedGLHelpers.h"
namespace mozilla {
namespace wr {
-static CGLError CreateTextureForPlane(uint8_t aPlaneID, gl::GLContext* aGL,
- MacIOSurface* aSurface,
- GLuint* aTexture) {
+static bool CreateTextureForPlane(uint8_t aPlaneID, gl::GLContext* aGL,
+ MacIOSurface* aSurface, GLuint* aTexture) {
MOZ_ASSERT(aGL && aSurface && aTexture);
aGL->fGenTextures(1, aTexture);
@@ -26,10 +30,8 @@ static CGLError CreateTextureForPlane(uint8_t aPlaneID, gl::GLContext* aGL,
aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S,
LOCAL_GL_CLAMP_TO_EDGE);
- CGLError result = kCGLNoError;
gfx::SurfaceFormat readFormat = gfx::SurfaceFormat::UNKNOWN;
- result = aSurface->CGLTexImageIOSurface2D(
- aGL, gl::GLContextCGL::Cast(aGL)->GetCGLContext(), aPlaneID, &readFormat);
+ bool result = aSurface->BindTexImage(aGL, aPlaneID, &readFormat);
// If this is a yuv format, the Webrender only supports YUV422 interleaving
// format.
MOZ_ASSERT(aSurface->GetFormat() != gfx::SurfaceFormat::YUV422 ||
@@ -89,7 +91,11 @@ wr::WrExternalImage RenderMacIOSurfaceTextureHost::Lock(uint8_t aChannelIndex,
}
if (!mTextureHandles[0]) {
+#ifdef XP_MACOSX
MOZ_ASSERT(gl::GLContextCGL::Cast(mGL.get())->GetCGLContext());
+#else
+ MOZ_ASSERT(gl::GLContextEAGL::Cast(mGL.get())->GetEAGLContext());
+#endif
// The result of GetPlaneCount() is 0 for single plane format, but it will
// be 2 if the format has 2 planar data.
diff --git a/gfx/webrender_bindings/RenderThread.cpp b/gfx/webrender_bindings/RenderThread.cpp
index 89fc339c03..e1a41ee225 100644
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -70,12 +70,15 @@ static mozilla::BackgroundHangMonitor* sBackgroundHangMonitor;
#ifdef DEBUG
static bool sRenderThreadEverStarted = false;
#endif
+size_t RenderThread::sRendererCount = 0;
+size_t RenderThread::sActiveRendererCount = 0;
RenderThread::RenderThread(RefPtr<nsIThread> aThread)
: mThread(std::move(aThread)),
mThreadPool(false),
mThreadPoolLP(true),
mSingletonGLIsForHardwareWebRender(true),
+ mBatteryInfo("RenderThread.mBatteryInfo"),
mWindowInfos("RenderThread.mWindowInfos"),
mRenderTextureMapLock("RenderThread.mRenderTextureMapLock"),
mHasShutdown(false),
@@ -149,6 +152,11 @@ void RenderThread::Start(uint32_t aNamespace) {
}
sRenderThread = new RenderThread(thread);
+ CrashReporter::RegisterAnnotationUSize(
+ CrashReporter::Annotation::GraphicsNumRenderers, &sRendererCount);
+ CrashReporter::RegisterAnnotationUSize(
+ CrashReporter::Annotation::GraphicsNumActiveRenderers,
+ &sActiveRendererCount);
#ifdef XP_WIN
widget::WinCompositorWindowThread::Start();
#endif
@@ -291,6 +299,26 @@ RefPtr<MemoryReportPromise> RenderThread::AccumulateMemoryReport(
return p;
}
+void RenderThread::SetBatteryInfo(const hal::BatteryInformation& aBatteryInfo) {
+ MOZ_ASSERT(XRE_IsGPUProcess());
+
+ auto batteryInfo = mBatteryInfo.Lock();
+ batteryInfo.ref() = Some(aBatteryInfo);
+}
+
+bool RenderThread::GetPowerIsCharging() {
+ MOZ_ASSERT(XRE_IsGPUProcess());
+
+ auto batteryInfo = mBatteryInfo.Lock();
+ if (batteryInfo.ref().isSome()) {
+ return batteryInfo.ref().ref().charging();
+ }
+
+ gfxCriticalNoteOnce << "BatteryInfo is not set";
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ return false;
+}
+
void RenderThread::AddRenderer(wr::WindowId aWindowId,
UniquePtr<RendererOGL> aRenderer) {
MOZ_ASSERT(IsInRenderThread());
@@ -301,9 +329,7 @@ void RenderThread::AddRenderer(wr::WindowId aWindowId,
}
mRenderers[aWindowId] = std::move(aRenderer);
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::GraphicsNumRenderers,
- (unsigned int)mRenderers.size());
+ sRendererCount = mRenderers.size();
auto windows = mWindowInfos.Lock();
windows->emplace(AsUint64(aWindowId), new WindowInfo());
@@ -321,9 +347,7 @@ void RenderThread::RemoveRenderer(wr::WindowId aWindowId) {
}
mRenderers.erase(aWindowId);
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::GraphicsNumRenderers,
- (unsigned int)mRenderers.size());
+ sRendererCount = mRenderers.size();
if (mRenderers.empty()) {
if (mHandlingDeviceReset) {
@@ -370,7 +394,7 @@ size_t RenderThread::RendererCount() const {
return mRenderers.size();
}
-size_t RenderThread::ActiveRendererCount() const {
+void RenderThread::UpdateActiveRendererCount() {
MOZ_ASSERT(IsInRenderThread());
size_t num_active = 0;
for (const auto& it : mRenderers) {
@@ -378,7 +402,7 @@ size_t RenderThread::ActiveRendererCount() const {
num_active++;
}
}
- return num_active;
+ sActiveRendererCount = num_active;
}
void RenderThread::WrNotifierEvent_WakeUp(WrWindowId aWindowId,
@@ -842,9 +866,7 @@ void RenderThread::Pause(wr::WindowId aWindowId) {
auto& renderer = it->second;
renderer->Pause();
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::GraphicsNumActiveRenderers,
- (unsigned int)ActiveRendererCount());
+ UpdateActiveRendererCount();
}
bool RenderThread::Resume(wr::WindowId aWindowId) {
@@ -861,9 +883,7 @@ bool RenderThread::Resume(wr::WindowId aWindowId) {
auto& renderer = it->second;
bool resumed = renderer->Resume();
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::GraphicsNumActiveRenderers,
- (unsigned int)ActiveRendererCount());
+ UpdateActiveRendererCount();
return resumed;
}
@@ -1378,7 +1398,7 @@ RenderThread::GetProgramsForCompositorOGL() {
}
RefPtr<layers::SurfacePool> RenderThread::SharedSurfacePool() {
-#if defined(XP_MACOSX) || defined(MOZ_WAYLAND)
+#if defined(XP_DARWIN) || defined(MOZ_WAYLAND)
if (!mSurfacePool) {
size_t poolSizeLimit =
StaticPrefs::gfx_webrender_compositor_surface_pool_size_AtStartup();
@@ -1555,7 +1575,7 @@ static already_AddRefed<gl::GLContext> CreateGLContextEGL() {
}
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
static already_AddRefed<gl::GLContext> CreateGLContextCGL() {
nsCString failureUnused;
return gl::GLContextProvider::CreateHeadless(
@@ -1578,7 +1598,7 @@ static already_AddRefed<gl::GLContext> CreateGLContext(nsACString& aError) {
if (gfx::gfxVars::UseEGL()) {
gl = CreateGLContextEGL();
}
-#elif XP_MACOSX
+#elif XP_DARWIN
gl = CreateGLContextCGL();
#endif
diff --git a/gfx/webrender_bindings/RenderThread.h b/gfx/webrender_bindings/RenderThread.h
index aa508e5581..f9ab1e742e 100644
--- a/gfx/webrender_bindings/RenderThread.h
+++ b/gfx/webrender_bindings/RenderThread.h
@@ -14,6 +14,7 @@
#include "GLTypes.h" // for GLenum
#include "nsISupportsImpl.h"
#include "mozilla/gfx/Point.h"
+#include "mozilla/Hal.h"
#include "mozilla/MozPromise.h"
#include "mozilla/DataMutex.h"
#include "mozilla/Maybe.h"
@@ -292,7 +293,8 @@ class RenderThread final {
bool SyncObjectNeeded();
size_t RendererCount() const;
- size_t ActiveRendererCount() const;
+ size_t ActiveRendererCount() const { return sActiveRendererCount; };
+ void UpdateActiveRendererCount();
void BeginRecordingForWindow(wr::WindowId aWindowId,
const TimeStamp& aRecordingStart,
@@ -302,7 +304,13 @@ class RenderThread final {
static void MaybeEnableGLDebugMessage(gl::GLContext* aGLContext);
+ void SetBatteryInfo(const hal::BatteryInformation& aBatteryInfo);
+ bool GetPowerIsCharging();
+
private:
+ static size_t sRendererCount;
+ static size_t sActiveRendererCount;
+
enum class RenderTextureOp {
PrepareForUse,
NotifyForUse,
@@ -434,6 +442,8 @@ class RenderThread final {
std::map<wr::WindowId, UniquePtr<RendererOGL>> mRenderers;
+ DataMutex<Maybe<hal::BatteryInformation>> mBatteryInfo;
+
struct PendingFrameInfo {
TimeStamp mStartTime;
VsyncId mStartId;
diff --git a/gfx/webrender_bindings/moz.build b/gfx/webrender_bindings/moz.build
index f17c77e4cb..6cca348acb 100644
--- a/gfx/webrender_bindings/moz.build
+++ b/gfx/webrender_bindings/moz.build
@@ -51,7 +51,7 @@ UNIFIED_SOURCES += [
"WebRenderTypes.cpp",
]
-if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
EXPORTS.mozilla.webrender += [
"RenderCompositorNative.h",
"RenderMacIOSurfaceTextureHost.h",
diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs
index 1f3bca644a..047791c76b 100644
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -7,7 +7,7 @@
use gleam::gl;
use std::cell::RefCell;
-#[cfg(not(target_os = "macos"))]
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
use std::ffi::OsString;
use std::ffi::{CStr, CString};
use std::io::Cursor;
@@ -16,7 +16,7 @@ use std::ops::Range;
#[cfg(target_os = "android")]
use std::os::raw::c_int;
use std::os::raw::{c_char, c_float, c_void};
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
use std::os::unix::ffi::OsStringExt;
#[cfg(target_os = "windows")]
use std::os::windows::ffi::OsStringExt;
@@ -2326,7 +2326,7 @@ fn read_font_descriptor(bytes: &mut WrVecU8, index: u32) -> NativeFontHandle {
}
}
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
fn read_font_descriptor(bytes: &mut WrVecU8, index: u32) -> NativeFontHandle {
// On macOS, the descriptor string is a concatenation of the PostScript name
// and the font file path (to disambiguate cases where there are multiple
@@ -2340,7 +2340,7 @@ fn read_font_descriptor(bytes: &mut WrVecU8, index: u32) -> NativeFontHandle {
}
}
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
fn read_font_descriptor(bytes: &mut WrVecU8, index: u32) -> NativeFontHandle {
let chars = bytes.flush_into_vec();
NativeFontHandle {
diff --git a/gfx/webrender_bindings/src/lib.rs b/gfx/webrender_bindings/src/lib.rs
index 9e94302e0f..b3c6e6ac56 100644
--- a/gfx/webrender_bindings/src/lib.rs
+++ b/gfx/webrender_bindings/src/lib.rs
@@ -28,11 +28,11 @@ extern crate dwrote;
#[cfg(target_os = "windows")]
extern crate winapi;
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
extern crate core_foundation;
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
extern crate core_graphics;
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
extern crate foreign_types;
mod program_cache;
diff --git a/gfx/webrender_bindings/src/moz2d_renderer.rs b/gfx/webrender_bindings/src/moz2d_renderer.rs
index 4c7a32c912..ca1e76f96f 100644
--- a/gfx/webrender_bindings/src/moz2d_renderer.rs
+++ b/gfx/webrender_bindings/src/moz2d_renderer.rs
@@ -33,16 +33,16 @@ use std::sync::Arc;
#[cfg(target_os = "windows")]
use dwrote;
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
use core_foundation::string::CFString;
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
use core_graphics::font::CGFont;
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
use foreign_types::ForeignType;
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
use std::ffi::CString;
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
use std::os::unix::ffi::OsStrExt;
/// Local print-debugging utility
@@ -787,7 +787,7 @@ impl Moz2dBlobImageHandler {
unsafe { AddNativeFontHandle(key, face.as_ptr() as *mut c_void, 0) };
}
- #[cfg(target_os = "macos")]
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
fn process_native_font_handle(key: FontKey, handle: &NativeFontHandle) {
let font = match CGFont::from_name(&CFString::new(&handle.name)) {
Ok(font) => font,
@@ -804,7 +804,7 @@ impl Moz2dBlobImageHandler {
unsafe { AddNativeFontHandle(key, font.as_ptr() as *mut c_void, 0) };
}
- #[cfg(not(any(target_os = "macos", target_os = "windows")))]
+ #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
fn process_native_font_handle(key: FontKey, handle: &NativeFontHandle) {
let cstr = CString::new(handle.path.as_os_str().as_bytes()).unwrap();
unsafe { AddNativeFontHandle(key, cstr.as_ptr() as *mut c_void, handle.index) };
diff --git a/gfx/wgpu_bindings/Cargo.toml b/gfx/wgpu_bindings/Cargo.toml
index b24d09a955..21b4b8c7f7 100644
--- a/gfx/wgpu_bindings/Cargo.toml
+++ b/gfx/wgpu_bindings/Cargo.toml
@@ -17,7 +17,7 @@ default = []
[dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
-rev = "07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a"
+rev = "6040820099bc72b827a6a5f53d66dda3e301f944"
# TODO: remove the replay feature on the next update containing https://github.com/gfx-rs/wgpu/pull/5182
features = ["serde", "replay", "trace", "strict_asserts", "wgsl", "api_log_info"]
@@ -26,37 +26,37 @@ features = ["serde", "replay", "trace", "strict_asserts", "wgsl", "api_log_info"
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
-rev = "07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a"
+rev = "6040820099bc72b827a6a5f53d66dda3e301f944"
features = ["metal"]
# We want the wgpu-core Direct3D backends on Windows.
[target.'cfg(windows)'.dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
-rev = "07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a"
+rev = "6040820099bc72b827a6a5f53d66dda3e301f944"
features = ["dx12"]
# We want the wgpu-core Vulkan backend on Linux and Windows.
[target.'cfg(any(windows, all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
-rev = "07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a"
+rev = "6040820099bc72b827a6a5f53d66dda3e301f944"
features = ["vulkan"]
[dependencies.wgt]
package = "wgpu-types"
git = "https://github.com/gfx-rs/wgpu"
-rev = "07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a"
+rev = "6040820099bc72b827a6a5f53d66dda3e301f944"
[dependencies.wgh]
package = "wgpu-hal"
git = "https://github.com/gfx-rs/wgpu"
-rev = "07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a"
+rev = "6040820099bc72b827a6a5f53d66dda3e301f944"
features = ["windows_rs"]
[target.'cfg(windows)'.dependencies.d3d12]
git = "https://github.com/gfx-rs/wgpu"
-rev = "07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a"
+rev = "6040820099bc72b827a6a5f53d66dda3e301f944"
[target.'cfg(windows)'.dependencies]
winapi = "0.3"
@@ -68,3 +68,4 @@ parking_lot = "0.12"
serde = "1"
nsstring = { path = "../../xpcom/rust/nsstring" }
static_prefs = { path = "../../modules/libpref/init/static_prefs" }
+arrayvec = "0.7"
diff --git a/gfx/wgpu_bindings/moz.yaml b/gfx/wgpu_bindings/moz.yaml
index 1c4f19cbb7..ffa746cb46 100644
--- a/gfx/wgpu_bindings/moz.yaml
+++ b/gfx/wgpu_bindings/moz.yaml
@@ -20,11 +20,11 @@ origin:
# Human-readable identifier for this version/release
# Generally "version NNN", "tag SSS", "bookmark SSS"
- release: commit 07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a
+ release: 6040820099bc72b827a6a5f53d66dda3e301f944 (2024-03-12T14:49:44Z).
# Revision to pull in
# Must be a long or short commit SHA (long preferred)
- revision: 07e59eb6fc7de3f682f1c401b9cf9f0da9ee4b4a
+ revision: 6040820099bc72b827a6a5f53d66dda3e301f944
license: ['MIT', 'Apache-2.0']
diff --git a/gfx/wgpu_bindings/src/client.rs b/gfx/wgpu_bindings/src/client.rs
index bf53a8c871..c49dbea7a5 100644
--- a/gfx/wgpu_bindings/src/client.rs
+++ b/gfx/wgpu_bindings/src/client.rs
@@ -47,7 +47,7 @@ impl ProgrammableStageDescriptor {
fn to_wgpu(&self) -> wgc::pipeline::ProgrammableStageDescriptor {
wgc::pipeline::ProgrammableStageDescriptor {
module: self.module,
- entry_point: cow_label(&self.entry_point).unwrap(),
+ entry_point: cow_label(&self.entry_point),
}
}
}
@@ -177,6 +177,7 @@ pub enum RawBindingType {
SampledTexture,
ReadonlyStorageTexture,
WriteonlyStorageTexture,
+ ReadWriteStorageTexture,
}
#[repr(C)]
@@ -237,7 +238,7 @@ pub struct SamplerDescriptor<'a> {
lod_min_clamp: f32,
lod_max_clamp: f32,
compare: Option<&'a wgt::CompareFunction>,
- anisotropy_clamp: Option<&'a u16>,
+ max_anisotropy: u16,
}
#[repr(C)]
@@ -614,7 +615,7 @@ pub extern "C" fn wgpu_client_create_sampler(
lod_min_clamp: desc.lod_min_clamp,
lod_max_clamp: desc.lod_max_clamp,
compare: desc.compare.cloned(),
- anisotropy_clamp: *desc.anisotropy_clamp.unwrap_or(&1),
+ anisotropy_clamp: desc.max_anisotropy,
border_color: None,
};
let action = DeviceAction::CreateSampler(id, wgpu_desc);
@@ -769,9 +770,8 @@ pub struct ComputePassTimestampWrites<'a> {
#[no_mangle]
pub unsafe extern "C" fn wgpu_command_encoder_begin_compute_pass(
- encoder_id: id::CommandEncoderId,
desc: &ComputePassDescriptor,
-) -> *mut wgc::command::ComputePass {
+) -> *mut crate::command::RecordedComputePass {
let &ComputePassDescriptor {
label,
timestamp_writes,
@@ -795,27 +795,24 @@ pub unsafe extern "C" fn wgpu_command_encoder_begin_compute_pass(
});
let timestamp_writes = timestamp_writes.as_ref();
- let pass = wgc::command::ComputePass::new(
- encoder_id,
- &wgc::command::ComputePassDescriptor {
- label,
- timestamp_writes,
- },
- );
+ let pass = crate::command::RecordedComputePass::new(&wgc::command::ComputePassDescriptor {
+ label,
+ timestamp_writes,
+ });
Box::into_raw(Box::new(pass))
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_compute_pass_finish(
- pass: *mut wgc::command::ComputePass,
+ pass: *mut crate::command::RecordedComputePass,
output: &mut ByteBuf,
) {
- let command = Box::from_raw(pass).into_command();
+ let command = Box::from_raw(pass);
*output = make_byte_buf(&command);
}
#[no_mangle]
-pub unsafe extern "C" fn wgpu_compute_pass_destroy(pass: *mut wgc::command::ComputePass) {
+pub unsafe extern "C" fn wgpu_compute_pass_destroy(pass: *mut crate::command::RecordedComputePass) {
let _ = Box::from_raw(pass);
}
@@ -838,9 +835,8 @@ pub struct RenderPassTimestampWrites<'a> {
#[no_mangle]
pub unsafe extern "C" fn wgpu_command_encoder_begin_render_pass(
- encoder_id: id::CommandEncoderId,
desc: &RenderPassDescriptor,
-) -> *mut wgc::command::RenderPass {
+) -> *mut crate::command::RecordedRenderPass {
let &RenderPassDescriptor {
label,
color_attachments,
@@ -873,30 +869,27 @@ pub unsafe extern "C" fn wgpu_command_encoder_begin_render_pass(
.iter()
.map(|format| Some(format.clone()))
.collect();
- let pass = wgc::command::RenderPass::new(
- encoder_id,
- &wgc::command::RenderPassDescriptor {
- label,
- color_attachments: Cow::Owned(color_attachments),
- depth_stencil_attachment: depth_stencil_attachment.as_ref(),
- timestamp_writes,
- occlusion_query_set,
- },
- );
+ let pass = crate::command::RecordedRenderPass::new(&wgc::command::RenderPassDescriptor {
+ label,
+ color_attachments: Cow::Owned(color_attachments),
+ depth_stencil_attachment: depth_stencil_attachment.as_ref(),
+ timestamp_writes,
+ occlusion_query_set,
+ });
Box::into_raw(Box::new(pass))
}
#[no_mangle]
pub unsafe extern "C" fn wgpu_render_pass_finish(
- pass: *mut wgc::command::RenderPass,
+ pass: *mut crate::command::RecordedRenderPass,
output: &mut ByteBuf,
) {
- let command = Box::from_raw(pass).into_command();
+ let command = Box::from_raw(pass);
*output = make_byte_buf(&command);
}
#[no_mangle]
-pub unsafe extern "C" fn wgpu_render_pass_destroy(pass: *mut wgc::command::RenderPass) {
+pub unsafe extern "C" fn wgpu_render_pass_destroy(pass: *mut crate::command::RecordedRenderPass) {
let _ = Box::from_raw(pass);
}
@@ -974,6 +967,11 @@ pub unsafe extern "C" fn wgpu_client_create_bind_group_layout(
view_dimension: *entry.view_dimension.unwrap(),
format: *entry.storage_texture_format.unwrap(),
},
+ RawBindingType::ReadWriteStorageTexture => wgt::BindingType::StorageTexture {
+ access: wgt::StorageTextureAccess::ReadWrite,
+ view_dimension: *entry.view_dimension.unwrap(),
+ format: *entry.storage_texture_format.unwrap(),
+ },
},
});
}
diff --git a/gfx/wgpu_bindings/src/command.rs b/gfx/wgpu_bindings/src/command.rs
new file mode 100644
index 0000000000..acba975c13
--- /dev/null
+++ b/gfx/wgpu_bindings/src/command.rs
@@ -0,0 +1,1062 @@
+/* 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/. */
+
+use crate::{id, RawString};
+use std::{borrow::Cow, ffi, slice};
+use wgc::{command::{compute_ffi, render_ffi, ComputePassDescriptor, ComputePassTimestampWrites, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, RenderPassTimestampWrites}, id::CommandEncoderId};
+use wgt::{BufferAddress, BufferSize, Color, DynamicOffset, IndexFormat};
+
+use serde::{Serialize, Deserialize};
+use arrayvec::ArrayVec;
+
+/// A stream of commands for a render pass or compute pass.
+///
+/// This also contains side tables referred to by certain commands,
+/// like dynamic offsets for [`SetBindGroup`] or string data for
+/// [`InsertDebugMarker`].
+///
+/// Render passes use `BasePass<RenderCommand>`, whereas compute
+/// passes use `BasePass<ComputeCommand>`.
+///
+/// [`SetBindGroup`]: RenderCommand::SetBindGroup
+/// [`InsertDebugMarker`]: RenderCommand::InsertDebugMarker
+#[doc(hidden)]
+#[derive(Debug)]
+#[derive(serde::Serialize, serde::Deserialize)]
+pub struct BasePass<C> {
+ pub label: Option<String>,
+
+ /// The stream of commands.
+ pub commands: Vec<C>,
+
+ /// Dynamic offsets consumed by [`SetBindGroup`] commands in `commands`.
+ ///
+ /// Each successive `SetBindGroup` consumes the next
+ /// [`num_dynamic_offsets`] values from this list.
+ pub dynamic_offsets: Vec<wgt::DynamicOffset>,
+
+ /// Strings used by debug instructions.
+ ///
+ /// Each successive [`PushDebugGroup`] or [`InsertDebugMarker`]
+ /// instruction consumes the next `len` bytes from this vector.
+ pub string_data: Vec<u8>,
+}
+
+#[derive(Deserialize, Serialize)]
+pub struct RecordedRenderPass {
+ base: BasePass<RenderCommand>,
+ color_attachments: ArrayVec<Option<RenderPassColorAttachment>, { wgh::MAX_COLOR_ATTACHMENTS }>,
+ depth_stencil_attachment: Option<RenderPassDepthStencilAttachment>,
+ timestamp_writes: Option<RenderPassTimestampWrites>,
+ occlusion_query_set_id: Option<id::QuerySetId>,
+}
+
+impl RecordedRenderPass {
+ pub fn new(desc: &RenderPassDescriptor) -> Self {
+ Self {
+ base: BasePass {
+ label: desc.label.as_ref().map(|cow| cow.to_string()),
+ commands: Vec::new(),
+ dynamic_offsets: Vec::new(),
+ string_data: Vec::new(),
+ },
+ color_attachments: desc.color_attachments.iter().cloned().collect(),
+ depth_stencil_attachment: desc.depth_stencil_attachment.cloned(),
+ timestamp_writes: desc.timestamp_writes.cloned(),
+ occlusion_query_set_id: desc.occlusion_query_set,
+ }
+ }
+}
+
+#[derive(serde::Deserialize, serde::Serialize)]
+pub struct RecordedComputePass {
+ base: BasePass<ComputeCommand>,
+ timestamp_writes: Option<ComputePassTimestampWrites>,
+}
+
+impl RecordedComputePass {
+ pub fn new(desc: &ComputePassDescriptor) -> Self {
+ Self {
+ base: BasePass {
+ label: desc.label.as_ref().map(|cow| cow.to_string()),
+ commands: Vec::new(),
+ dynamic_offsets: Vec::new(),
+ string_data: Vec::new(),
+ },
+ timestamp_writes: desc.timestamp_writes.cloned(),
+ }
+ }
+}
+
+#[doc(hidden)]
+#[derive(Clone, Copy, Debug)]
+#[derive(serde::Serialize, serde::Deserialize)]
+pub enum RenderCommand {
+ SetBindGroup {
+ index: u32,
+ num_dynamic_offsets: usize,
+ bind_group_id: id::BindGroupId,
+ },
+ SetPipeline(id::RenderPipelineId),
+ SetIndexBuffer {
+ buffer_id: id::BufferId,
+ index_format: wgt::IndexFormat,
+ offset: BufferAddress,
+ size: Option<BufferSize>,
+ },
+ SetVertexBuffer {
+ slot: u32,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+ size: Option<BufferSize>,
+ },
+ SetBlendConstant(Color),
+ SetStencilReference(u32),
+ SetViewport {
+ x: f32, y: f32, w: f32, h: f32,
+ depth_min: f32,
+ depth_max: f32,
+ },
+ SetScissor { x: u32, y: u32, w: u32, h: u32 },
+ Draw {
+ vertex_count: u32,
+ instance_count: u32,
+ first_vertex: u32,
+ first_instance: u32,
+ },
+ DrawIndexed {
+ index_count: u32,
+ instance_count: u32,
+ first_index: u32,
+ base_vertex: i32,
+ first_instance: u32,
+ },
+ MultiDrawIndirect {
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+ /// Count of `None` represents a non-multi call.
+ count: Option<u32>,
+ indexed: bool,
+ },
+ MultiDrawIndirectCount {
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+ count_buffer_id: id::BufferId,
+ count_buffer_offset: BufferAddress,
+ max_count: u32,
+ indexed: bool,
+ },
+ PushDebugGroup {
+ color: u32,
+ len: usize,
+ },
+ PopDebugGroup,
+ InsertDebugMarker {
+ color: u32,
+ len: usize,
+ },
+ WriteTimestamp {
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+ },
+ BeginOcclusionQuery {
+ query_index: u32,
+ },
+ EndOcclusionQuery,
+ BeginPipelineStatisticsQuery {
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+ },
+ EndPipelineStatisticsQuery,
+ ExecuteBundle(id::RenderBundleId),
+}
+
+#[doc(hidden)]
+#[derive(Clone, Copy, Debug)]
+#[derive(serde::Serialize, serde::Deserialize)]
+pub enum ComputeCommand {
+ SetBindGroup {
+ index: u32,
+ num_dynamic_offsets: usize,
+ bind_group_id: id::BindGroupId,
+ },
+ SetPipeline(id::ComputePipelineId),
+ Dispatch([u32; 3]),
+ DispatchIndirect {
+ buffer_id: id::BufferId,
+ offset: wgt::BufferAddress,
+ },
+ PushDebugGroup {
+ color: u32,
+ len: usize,
+ },
+ PopDebugGroup,
+ InsertDebugMarker {
+ color: u32,
+ len: usize,
+ },
+ WriteTimestamp {
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+ },
+ BeginPipelineStatisticsQuery {
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+ },
+ EndPipelineStatisticsQuery,
+}
+
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given pointer is
+/// valid for `offset_length` elements.
+#[no_mangle]
+pub unsafe extern "C" fn wgpu_recorded_render_pass_set_bind_group(
+ pass: &mut RecordedRenderPass,
+ index: u32,
+ bind_group_id: id::BindGroupId,
+ offsets: *const DynamicOffset,
+ offset_length: usize,
+) {
+ pass.base.dynamic_offsets
+ .extend_from_slice(unsafe { slice::from_raw_parts(offsets, offset_length) });
+
+ pass.base.commands.push(RenderCommand::SetBindGroup {
+ index,
+ num_dynamic_offsets: offset_length,
+ bind_group_id,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_set_pipeline(
+ pass: &mut RecordedRenderPass,
+ pipeline_id: id::RenderPipelineId,
+) {
+ pass.base
+ .commands
+ .push(RenderCommand::SetPipeline(pipeline_id));
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_set_vertex_buffer(
+ pass: &mut RecordedRenderPass,
+ slot: u32,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+ size: Option<BufferSize>,
+) {
+ pass.base.commands.push(RenderCommand::SetVertexBuffer {
+ slot,
+ buffer_id,
+ offset,
+ size,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_set_index_buffer(
+ pass: &mut RecordedRenderPass,
+ buffer_id: id::BufferId,
+ index_format: IndexFormat,
+ offset: BufferAddress,
+ size: Option<BufferSize>,
+) {
+ pass.base.commands.push(RenderCommand::SetIndexBuffer {
+ buffer_id,
+ index_format,
+ offset,
+ size,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_set_blend_constant(pass: &mut RecordedRenderPass, color: &Color) {
+ pass.base
+ .commands
+ .push(RenderCommand::SetBlendConstant(*color));
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_set_stencil_reference(pass: &mut RecordedRenderPass, value: u32) {
+ pass.base
+ .commands
+ .push(RenderCommand::SetStencilReference(value));
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_set_viewport(
+ pass: &mut RecordedRenderPass,
+ x: f32,
+ y: f32,
+ w: f32,
+ h: f32,
+ depth_min: f32,
+ depth_max: f32,
+) {
+ pass.base.commands.push(RenderCommand::SetViewport {
+ x, y, w, h,
+ depth_min,
+ depth_max,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_set_scissor_rect(
+ pass: &mut RecordedRenderPass,
+ x: u32,
+ y: u32,
+ w: u32,
+ h: u32,
+) {
+ pass.base
+ .commands
+ .push(RenderCommand::SetScissor { x, y, w, h });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_draw(
+ pass: &mut RecordedRenderPass,
+ vertex_count: u32,
+ instance_count: u32,
+ first_vertex: u32,
+ first_instance: u32,
+) {
+ pass.base.commands.push(RenderCommand::Draw {
+ vertex_count,
+ instance_count,
+ first_vertex,
+ first_instance,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_draw_indexed(
+ pass: &mut RecordedRenderPass,
+ index_count: u32,
+ instance_count: u32,
+ first_index: u32,
+ base_vertex: i32,
+ first_instance: u32,
+) {
+ pass.base.commands.push(RenderCommand::DrawIndexed {
+ index_count,
+ instance_count,
+ first_index,
+ base_vertex,
+ first_instance,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_draw_indirect(
+ pass: &mut RecordedRenderPass,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+) {
+ pass.base.commands.push(RenderCommand::MultiDrawIndirect {
+ buffer_id,
+ offset,
+ count: None,
+ indexed: false,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_draw_indexed_indirect(
+ pass: &mut RecordedRenderPass,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+) {
+ pass.base.commands.push(RenderCommand::MultiDrawIndirect {
+ buffer_id,
+ offset,
+ count: None,
+ indexed: true,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_multi_draw_indirect(
+ pass: &mut RecordedRenderPass,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+ count: u32,
+) {
+ pass.base.commands.push(RenderCommand::MultiDrawIndirect {
+ buffer_id,
+ offset,
+ count: Some(count),
+ indexed: false,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_multi_draw_indexed_indirect(
+ pass: &mut RecordedRenderPass,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+ count: u32,
+) {
+ pass.base.commands.push(RenderCommand::MultiDrawIndirect {
+ buffer_id,
+ offset,
+ count: Some(count),
+ indexed: true,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_multi_draw_indirect_count(
+ pass: &mut RecordedRenderPass,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+ count_buffer_id: id::BufferId,
+ count_buffer_offset: BufferAddress,
+ max_count: u32,
+) {
+ pass.base
+ .commands
+ .push(RenderCommand::MultiDrawIndirectCount {
+ buffer_id,
+ offset,
+ count_buffer_id,
+ count_buffer_offset,
+ max_count,
+ indexed: false,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_multi_draw_indexed_indirect_count(
+ pass: &mut RecordedRenderPass,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+ count_buffer_id: id::BufferId,
+ count_buffer_offset: BufferAddress,
+ max_count: u32,
+) {
+ pass.base
+ .commands
+ .push(RenderCommand::MultiDrawIndirectCount {
+ buffer_id,
+ offset,
+ count_buffer_id,
+ count_buffer_offset,
+ max_count,
+ indexed: true,
+ });
+}
+
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given `label`
+/// is a valid null-terminated string.
+#[no_mangle]
+pub unsafe extern "C" fn wgpu_recorded_render_pass_push_debug_group(
+ pass: &mut RecordedRenderPass,
+ label: RawString,
+ color: u32,
+) {
+ let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
+ pass.base.string_data.extend_from_slice(bytes);
+
+ pass.base.commands.push(RenderCommand::PushDebugGroup {
+ color,
+ len: bytes.len(),
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_pop_debug_group(pass: &mut RecordedRenderPass) {
+ pass.base.commands.push(RenderCommand::PopDebugGroup);
+}
+
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given `label`
+/// is a valid null-terminated string.
+#[no_mangle]
+pub unsafe extern "C" fn wgpu_recorded_render_pass_insert_debug_marker(
+ pass: &mut RecordedRenderPass,
+ label: RawString,
+ color: u32,
+) {
+ let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
+ pass.base.string_data.extend_from_slice(bytes);
+
+ pass.base.commands.push(RenderCommand::InsertDebugMarker {
+ color,
+ len: bytes.len(),
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_write_timestamp(
+ pass: &mut RecordedRenderPass,
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+) {
+ pass.base.commands.push(RenderCommand::WriteTimestamp {
+ query_set_id,
+ query_index,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_begin_occlusion_query(
+ pass: &mut RecordedRenderPass,
+ query_index: u32,
+) {
+ pass.base
+ .commands
+ .push(RenderCommand::BeginOcclusionQuery { query_index });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_end_occlusion_query(pass: &mut RecordedRenderPass) {
+ pass.base.commands.push(RenderCommand::EndOcclusionQuery);
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_begin_pipeline_statistics_query(
+ pass: &mut RecordedRenderPass,
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+) {
+ pass.base
+ .commands
+ .push(RenderCommand::BeginPipelineStatisticsQuery {
+ query_set_id,
+ query_index,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_render_pass_end_pipeline_statistics_query(pass: &mut RecordedRenderPass) {
+ pass.base
+ .commands
+ .push(RenderCommand::EndPipelineStatisticsQuery);
+}
+
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given pointer is
+/// valid for `render_bundle_ids_length` elements.
+#[no_mangle]
+pub unsafe extern "C" fn wgpu_recorded_render_pass_execute_bundles(
+ pass: &mut RecordedRenderPass,
+ render_bundle_ids: *const id::RenderBundleId,
+ render_bundle_ids_length: usize,
+) {
+ for &bundle_id in
+ unsafe { slice::from_raw_parts(render_bundle_ids, render_bundle_ids_length) }
+ {
+ pass.base
+ .commands
+ .push(RenderCommand::ExecuteBundle(bundle_id));
+ }
+}
+
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given pointer is
+/// valid for `offset_length` elements.
+#[no_mangle]
+pub unsafe extern "C" fn wgpu_recorded_compute_pass_set_bind_group(
+ pass: &mut RecordedComputePass,
+ index: u32,
+ bind_group_id: id::BindGroupId,
+ offsets: *const DynamicOffset,
+ offset_length: usize,
+) {
+ pass.base.dynamic_offsets
+ .extend_from_slice(unsafe { slice::from_raw_parts(offsets, offset_length) });
+
+ pass.base.commands.push(ComputeCommand::SetBindGroup {
+ index,
+ num_dynamic_offsets: offset_length,
+ bind_group_id,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_compute_pass_set_pipeline(
+ pass: &mut RecordedComputePass,
+ pipeline_id: id::ComputePipelineId,
+) {
+ pass.base
+ .commands
+ .push(ComputeCommand::SetPipeline(pipeline_id));
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_compute_pass_dispatch_workgroups(
+ pass: &mut RecordedComputePass,
+ groups_x: u32,
+ groups_y: u32,
+ groups_z: u32,
+) {
+ pass.base
+ .commands
+ .push(ComputeCommand::Dispatch([groups_x, groups_y, groups_z]));
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_compute_pass_dispatch_workgroups_indirect(
+ pass: &mut RecordedComputePass,
+ buffer_id: id::BufferId,
+ offset: BufferAddress,
+) {
+ pass.base
+ .commands
+ .push(ComputeCommand::DispatchIndirect { buffer_id, offset });
+}
+
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given `label`
+/// is a valid null-terminated string.
+#[no_mangle]
+pub unsafe extern "C" fn wgpu_recorded_compute_pass_push_debug_group(
+ pass: &mut RecordedComputePass,
+ label: RawString,
+ color: u32,
+) {
+ let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
+ pass.base.string_data.extend_from_slice(bytes);
+
+ pass.base.commands.push(ComputeCommand::PushDebugGroup {
+ color,
+ len: bytes.len(),
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_compute_pass_pop_debug_group(pass: &mut RecordedComputePass) {
+ pass.base.commands.push(ComputeCommand::PopDebugGroup);
+}
+
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given `label`
+/// is a valid null-terminated string.
+#[no_mangle]
+pub unsafe extern "C" fn wgpu_recorded_compute_pass_insert_debug_marker(
+ pass: &mut RecordedComputePass,
+ label: RawString,
+ color: u32,
+) {
+ let bytes = unsafe { ffi::CStr::from_ptr(label) }.to_bytes();
+ pass.base.string_data.extend_from_slice(bytes);
+
+ pass.base.commands.push(ComputeCommand::InsertDebugMarker {
+ color,
+ len: bytes.len(),
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_compute_pass_write_timestamp(
+ pass: &mut RecordedComputePass,
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+) {
+ pass.base.commands.push(ComputeCommand::WriteTimestamp {
+ query_set_id,
+ query_index,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_compute_pass_begin_pipeline_statistics_query(
+ pass: &mut RecordedComputePass,
+ query_set_id: id::QuerySetId,
+ query_index: u32,
+) {
+ pass.base
+ .commands
+ .push(ComputeCommand::BeginPipelineStatisticsQuery {
+ query_set_id,
+ query_index,
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn wgpu_recorded_compute_pass_end_pipeline_statistics_query(pass: &mut RecordedComputePass) {
+ pass.base
+ .commands
+ .push(ComputeCommand::EndPipelineStatisticsQuery);
+}
+
+pub fn replay_render_pass(
+ id: CommandEncoderId,
+ src_pass: &RecordedRenderPass
+) -> wgc::command::RenderPass {
+
+ let mut dst_pass = wgc::command::RenderPass::new(
+ id,
+ &wgc::command::RenderPassDescriptor {
+ label: src_pass.base.label.as_ref().map(|s| s.as_str().into()),
+ color_attachments: Cow::Borrowed(&src_pass.color_attachments),
+ depth_stencil_attachment: src_pass.depth_stencil_attachment.as_ref(),
+ timestamp_writes: src_pass.timestamp_writes.as_ref(),
+ occlusion_query_set: src_pass.occlusion_query_set_id,
+ },
+ );
+
+ let mut dynamic_offsets = src_pass.base.dynamic_offsets.as_slice();
+ let mut dynamic_offsets = |len| {
+ let offsets;
+ (offsets, dynamic_offsets) = dynamic_offsets.split_at(len);
+ offsets
+ };
+ let mut strings = src_pass.base.string_data.as_slice();
+ let mut strings = |len| {
+ let label;
+ (label, strings) = strings.split_at(len);
+ label
+ };
+ for command in &src_pass.base.commands {
+ match *command {
+ RenderCommand::SetBindGroup {
+ index,
+ num_dynamic_offsets,
+ bind_group_id,
+ } => {
+ let offsets = dynamic_offsets(num_dynamic_offsets);
+ unsafe {
+ render_ffi::wgpu_render_pass_set_bind_group(
+ &mut dst_pass,
+ index,
+ bind_group_id,
+ offsets.as_ptr(),
+ offsets.len(),
+ );
+ }
+ }
+ RenderCommand::SetPipeline(pipeline_id) => {
+ render_ffi::wgpu_render_pass_set_pipeline(&mut dst_pass, pipeline_id);
+ }
+ RenderCommand::SetIndexBuffer {
+ buffer_id,
+ index_format,
+ offset,
+ size,
+ } => {
+ render_ffi::wgpu_render_pass_set_index_buffer(
+ &mut dst_pass,
+ buffer_id,
+ index_format,
+ offset,
+ size
+ );
+ }
+ RenderCommand::SetVertexBuffer {
+ slot,
+ buffer_id,
+ offset,
+ size,
+ } => {
+ render_ffi::wgpu_render_pass_set_vertex_buffer(
+ &mut dst_pass,
+ slot,
+ buffer_id,
+ offset,
+ size
+ )
+ }
+ RenderCommand::SetBlendConstant(ref color) => {
+ render_ffi::wgpu_render_pass_set_blend_constant(&mut dst_pass, color);
+ }
+ RenderCommand::SetStencilReference(value) => {
+ render_ffi::wgpu_render_pass_set_stencil_reference(&mut dst_pass, value);
+ }
+ RenderCommand::SetViewport {
+ x, y, w, h,
+ depth_min,
+ depth_max,
+ } => {
+ render_ffi::wgpu_render_pass_set_viewport(
+ &mut dst_pass,
+ x, y, w, h,
+ depth_min,
+ depth_max,
+ );
+ }
+ RenderCommand::SetScissor { x, y, w, h } => {
+ render_ffi::wgpu_render_pass_set_scissor_rect(
+ &mut dst_pass,
+ x, y, w, h
+ );
+ }
+ RenderCommand::Draw {
+ vertex_count,
+ instance_count,
+ first_vertex,
+ first_instance,
+ } => {
+ render_ffi::wgpu_render_pass_draw(
+ &mut dst_pass,
+ vertex_count,
+ instance_count,
+ first_vertex,
+ first_instance,
+ );
+ }
+ RenderCommand::DrawIndexed {
+ index_count,
+ instance_count,
+ first_index,
+ base_vertex,
+ first_instance,
+ } => {
+ render_ffi::wgpu_render_pass_draw_indexed(
+ &mut dst_pass,
+ index_count,
+ instance_count,
+ first_index,
+ base_vertex,
+ first_instance,
+ );
+ }
+ RenderCommand::MultiDrawIndirect {
+ buffer_id,
+ offset,
+ count,
+ indexed,
+ } => {
+ match (indexed, count) {
+ (false, Some(count)) => render_ffi::wgpu_render_pass_multi_draw_indirect(
+ &mut dst_pass,
+ buffer_id,
+ offset,
+ count,
+ ),
+ (false, None) => render_ffi::wgpu_render_pass_draw_indirect(
+ &mut dst_pass,
+ buffer_id,
+ offset,
+ ),
+ (true, Some(count)) => render_ffi::wgpu_render_pass_multi_draw_indexed_indirect(
+ &mut dst_pass,
+ buffer_id,
+ offset,
+ count,
+ ),
+ (true, None) => render_ffi::wgpu_render_pass_draw_indexed_indirect(
+ &mut dst_pass,
+ buffer_id,
+ offset,
+ ),
+ };
+ }
+ RenderCommand::MultiDrawIndirectCount {
+ buffer_id,
+ offset,
+ count_buffer_id,
+ count_buffer_offset,
+ max_count,
+ indexed,
+ } => {
+ if indexed {
+ render_ffi::wgpu_render_pass_multi_draw_indexed_indirect_count(
+ &mut dst_pass,
+ buffer_id,
+ offset,
+ count_buffer_id,
+ count_buffer_offset,
+ max_count,
+ );
+ } else {
+ render_ffi::wgpu_render_pass_multi_draw_indirect_count(
+ &mut dst_pass,
+ buffer_id,
+ offset,
+ count_buffer_id,
+ count_buffer_offset,
+ max_count,
+ );
+ }
+ }
+ RenderCommand::PushDebugGroup { color, len } => {
+ let label = strings(len);
+ let label = std::ffi::CString::new(label).unwrap();
+ unsafe {
+ render_ffi::wgpu_render_pass_push_debug_group(
+ &mut dst_pass,
+ label.as_ptr(),
+ color
+ );
+ }
+ }
+ RenderCommand::PopDebugGroup => {
+ render_ffi::wgpu_render_pass_pop_debug_group(&mut dst_pass);
+ }
+ RenderCommand::InsertDebugMarker { color, len } => {
+ let label = strings(len);
+ let label = std::ffi::CString::new(label).unwrap();
+ unsafe {
+ render_ffi::wgpu_render_pass_insert_debug_marker(
+ &mut dst_pass,
+ label.as_ptr(),
+ color,
+ );
+ }
+ }
+ RenderCommand::WriteTimestamp {
+ query_set_id,
+ query_index,
+ } => {
+ render_ffi::wgpu_render_pass_write_timestamp(
+ &mut dst_pass,
+ query_set_id,
+ query_index,
+ );
+ }
+ RenderCommand::BeginOcclusionQuery { query_index } => {
+ render_ffi::wgpu_render_pass_begin_occlusion_query(
+ &mut dst_pass,
+ query_index
+ );
+ }
+ RenderCommand::EndOcclusionQuery => {
+ render_ffi::wgpu_render_pass_end_occlusion_query(&mut dst_pass);
+ }
+ RenderCommand::BeginPipelineStatisticsQuery {
+ query_set_id,
+ query_index,
+ } => {
+ render_ffi::wgpu_render_pass_begin_pipeline_statistics_query(
+ &mut dst_pass,
+ query_set_id,
+ query_index,
+ );
+ }
+ RenderCommand::EndPipelineStatisticsQuery => {
+ render_ffi::wgpu_render_pass_end_pipeline_statistics_query(&mut dst_pass);
+ }
+ RenderCommand::ExecuteBundle(bundle_id) => {
+ unsafe {
+ render_ffi::wgpu_render_pass_execute_bundles(
+ &mut dst_pass,
+ &bundle_id,
+ 1,
+ );
+ }
+ }
+ }
+ }
+
+ dst_pass
+}
+
+pub fn replay_compute_pass(
+ id: CommandEncoderId,
+ src_pass: &RecordedComputePass
+) -> wgc::command::ComputePass {
+ let mut dst_pass = wgc::command::ComputePass::new(
+ id,
+ &wgc::command::ComputePassDescriptor {
+ label: src_pass.base.label.as_ref().map(|s| s.as_str().into()),
+ timestamp_writes: src_pass.timestamp_writes.as_ref(),
+ },
+ );
+
+ let mut dynamic_offsets = src_pass.base.dynamic_offsets.as_slice();
+ let mut dynamic_offsets = |len| {
+ let offsets;
+ (offsets, dynamic_offsets) = dynamic_offsets.split_at(len);
+ offsets
+ };
+ let mut strings = src_pass.base.string_data.as_slice();
+ let mut strings = |len| {
+ let label;
+ (label, strings) = strings.split_at(len);
+ label
+ };
+ for command in &src_pass.base.commands {
+ match *command {
+ ComputeCommand::SetBindGroup {
+ index,
+ num_dynamic_offsets,
+ bind_group_id,
+ } => {
+ let offsets = dynamic_offsets(num_dynamic_offsets);
+ unsafe {
+ compute_ffi::wgpu_compute_pass_set_bind_group(
+ &mut dst_pass,
+ index,
+ bind_group_id,
+ offsets.as_ptr(),
+ offsets.len()
+ );
+ }
+ }
+ ComputeCommand::SetPipeline(pipeline_id) => {
+ compute_ffi::wgpu_compute_pass_set_pipeline(&mut dst_pass, pipeline_id)
+ }
+ ComputeCommand::Dispatch([x, y, z]) => {
+ compute_ffi::wgpu_compute_pass_dispatch_workgroups(&mut dst_pass, x, y, z);
+ }
+ ComputeCommand::DispatchIndirect { buffer_id, offset } => {
+ compute_ffi::wgpu_compute_pass_dispatch_workgroups_indirect(
+ &mut dst_pass,
+ buffer_id,
+ offset,
+ );
+ }
+ ComputeCommand::PushDebugGroup { color, len } => {
+ let label = strings(len);
+ let label = std::ffi::CString::new(label).unwrap();
+ unsafe {
+ compute_ffi::wgpu_compute_pass_push_debug_group(
+ &mut dst_pass,
+ label.as_ptr(),
+ color
+ );
+ }
+ }
+ ComputeCommand::PopDebugGroup => {
+ compute_ffi::wgpu_compute_pass_pop_debug_group(&mut dst_pass);
+ }
+ ComputeCommand::InsertDebugMarker { color, len } => {
+ let label = strings(len);
+ let label = std::ffi::CString::new(label).unwrap();
+ unsafe {
+ compute_ffi::wgpu_compute_pass_insert_debug_marker(
+ &mut dst_pass,
+ label.as_ptr(),
+ color,
+ );
+ }
+ }
+ ComputeCommand::WriteTimestamp {
+ query_set_id,
+ query_index,
+ } => {
+ compute_ffi::wgpu_compute_pass_write_timestamp(
+ &mut dst_pass,
+ query_set_id,
+ query_index,
+ );
+ }
+ ComputeCommand::BeginPipelineStatisticsQuery {
+ query_set_id,
+ query_index,
+ } => {
+ compute_ffi::wgpu_compute_pass_begin_pipeline_statistics_query(
+ &mut dst_pass,
+ query_set_id,
+ query_index,
+ );
+ }
+ ComputeCommand::EndPipelineStatisticsQuery => {
+ compute_ffi::wgpu_compute_pass_end_pipeline_statistics_query(&mut dst_pass);
+ }
+ }
+ }
+
+ dst_pass
+}
diff --git a/gfx/wgpu_bindings/src/lib.rs b/gfx/wgpu_bindings/src/lib.rs
index 3299234182..6e6b79c991 100644
--- a/gfx/wgpu_bindings/src/lib.rs
+++ b/gfx/wgpu_bindings/src/lib.rs
@@ -10,6 +10,7 @@ pub use wgc::command::{compute_ffi::*, render_ffi::*};
pub mod client;
pub mod error;
pub mod server;
+pub mod command;
pub use wgc::device::trace::Command as CommandEncoderAction;
diff --git a/gfx/wgpu_bindings/src/server.rs b/gfx/wgpu_bindings/src/server.rs
index 7a7e08aa30..8417fe84fb 100644
--- a/gfx/wgpu_bindings/src/server.rs
+++ b/gfx/wgpu_bindings/src/server.rs
@@ -410,7 +410,9 @@ pub extern "C" fn wgpu_server_device_create_shader_module(
if let Some(err) = error {
out_message.set_error(&err, &source_str[..]);
let err_type = match &err {
- CreateShaderModuleError::Device(DeviceError::OutOfMemory) => ErrorBufferType::OutOfMemory,
+ CreateShaderModuleError::Device(DeviceError::OutOfMemory) => {
+ ErrorBufferType::OutOfMemory
+ }
CreateShaderModuleError::Device(DeviceError::Lost) => ErrorBufferType::DeviceLost,
_ => ErrorBufferType::Validation,
};
@@ -497,7 +499,8 @@ pub unsafe extern "C" fn wgpu_server_buffer_map(
// the returned value of buffer_map_async.
let result = gfx_select!(buffer_id => global.buffer_map_async(
buffer_id,
- start .. start + size,
+ start,
+ Some(size),
operation
));
@@ -580,9 +583,10 @@ pub extern "C" fn wgpu_server_get_device_fence_handle(
if device_id.backend() == wgt::Backend::Dx12 {
let mut handle = ptr::null_mut();
let dx12_device = unsafe {
- global.device_as_hal::<wgc::api::Dx12, _, Option<d3d12::Device>>(device_id, |hal_device| {
- hal_device.map(|device| device.raw_device().clone())
- })
+ global.device_as_hal::<wgc::api::Dx12, _, Option<d3d12::Device>>(
+ device_id,
+ |hal_device| hal_device.map(|device| device.raw_device().clone()),
+ )
};
let dx12_device = match dx12_device {
Some(device) => device,
@@ -592,9 +596,10 @@ pub extern "C" fn wgpu_server_get_device_fence_handle(
};
let dx12_fence = unsafe {
- global.device_fence_as_hal::<wgc::api::Dx12, _, Option<d3d12::Fence>>(device_id, |hal_fence| {
- hal_fence.map(|fence| fence.raw_fence().clone())
- })
+ global.device_fence_as_hal::<wgc::api::Dx12, _, Option<d3d12::Fence>>(
+ device_id,
+ |hal_fence| hal_fence.map(|fence| fence.raw_fence().clone()),
+ )
};
let dx12_fence = match dx12_fence {
Some(fence) => fence,
@@ -1054,6 +1059,32 @@ pub unsafe extern "C" fn wgpu_server_command_encoder_action(
}
#[no_mangle]
+pub unsafe extern "C" fn wgpu_server_render_pass(
+ global: &Global,
+ encoder_id: id::CommandEncoderId,
+ byte_buf: &ByteBuf,
+ error_buf: ErrorBuffer,
+) {
+ let pass = bincode::deserialize(byte_buf.as_slice()).unwrap();
+ let action = crate::command::replay_render_pass(encoder_id, &pass).into_command();
+
+ gfx_select!(encoder_id => global.command_encoder_action(encoder_id, action, error_buf));
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn wgpu_server_compute_pass(
+ global: &Global,
+ encoder_id: id::CommandEncoderId,
+ byte_buf: &ByteBuf,
+ error_buf: ErrorBuffer,
+) {
+ let pass = bincode::deserialize(byte_buf.as_slice()).unwrap();
+ let action = crate::command::replay_compute_pass(encoder_id, &pass).into_command();
+
+ gfx_select!(encoder_id => global.command_encoder_action(encoder_id, action, error_buf));
+}
+
+#[no_mangle]
pub extern "C" fn wgpu_server_device_create_encoder(
global: &Global,
self_id: id::DeviceId,
diff --git a/gfx/wr/Cargo.lock b/gfx/wr/Cargo.lock
index 02491f3993..2bf28a1b6e 100644
--- a/gfx/wr/Cargo.lock
+++ b/gfx/wr/Cargo.lock
@@ -996,29 +996,22 @@ dependencies = [
[[package]]
name = "glean"
-version = "57.0.0"
+version = "58.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae5847ad58b7f925c984de7f4dffcad67d7d0befa59a5a888cf93741b5ef1e6a"
+checksum = "f58388f10d013e2d12bb58e6e76983ede120789956fe827913a3d2560c66d44d"
dependencies = [
- "chrono",
- "crossbeam-channel",
"glean-core",
"inherent",
"log",
"once_cell",
- "serde",
- "serde_json",
- "thiserror",
- "time",
- "uuid",
"whatsys",
]
[[package]]
name = "glean-core"
-version = "57.0.0"
+version = "58.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6831cadd28b625bc296732d71dc7c978f208ba27911cad072785f87f23b1e634"
+checksum = "ed9acc46fd38c5c995a0537e76364496addace660839dc279079e5957e3c1093"
dependencies = [
"android_logger",
"bincode",
@@ -1121,9 +1114,9 @@ dependencies = [
[[package]]
name = "glslopt"
-version = "0.1.9"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74a3f5c04450dfdadb4b08f6e5ee6f5110f674de1acbd6199bfec68392a8cbaf"
+checksum = "ee5be629003d587bab188f3e2e3b010aa2cde7c41ec967b3a244f388d4d81877"
dependencies = [
"cc",
]
diff --git a/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs b/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs
index ac20b2b922..9e26b22fba 100644
--- a/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs
+++ b/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs
@@ -12,23 +12,6 @@ use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{Ident, Index, TraitBound};
use synstructure::{decl_derive, Structure, BindStyle, AddBounds};
-use unicode_xid::UnicodeXID;
-
-// Internal method for sanitizing an identifier for hygiene purposes.
-fn sanitize_ident(s: &str) -> Ident {
- let mut res = String::with_capacity(s.len());
- for mut c in s.chars() {
- if !UnicodeXID::is_xid_continue(c) {
- c = '_'
- }
- // Deduplicate consecutive _ characters.
- if res.ends_with('_') && c == '_' {
- continue;
- }
- res.push(c);
- }
- Ident::new(&res, Span::call_site())
-}
/// Calculates size type for number of variants (used for enums)
fn get_discriminant_size_type(len: usize) -> TokenStream {
@@ -241,11 +224,9 @@ fn peek_poke_derive(mut s: Structure) -> TokenStream {
s.add_trait_bounds(&default_trait, &mut where_clause, AddBounds::Generics);
s.add_trait_bounds(&peek_trait, &mut where_clause, AddBounds::Generics);
- let dummy_const: Ident = sanitize_ident(&format!("_DERIVE_peek_poke_Peek_FOR_{}", name));
-
let peek_impl = quote! {
#[allow(non_upper_case_globals)]
- const #dummy_const: () = {
+ const _: () = {
extern crate peek_poke;
impl #impl_generics peek_poke::Peek for #name #ty_generics #where_clause {
diff --git a/gfx/wr/webrender/Cargo.toml b/gfx/wr/webrender/Cargo.toml
index ed364fc34d..506226beca 100644
--- a/gfx/wr/webrender/Cargo.toml
+++ b/gfx/wr/webrender/Cargo.toml
@@ -18,12 +18,12 @@ serialize_program = ["serde", "webrender_build/serialize_program"]
dynamic_freetype = ["glyph_rasterizer/dynamic_freetype"]
static_freetype = ["glyph_rasterizer/static_freetype"]
leak_checks = []
-gecko = ["firefox-on-glean", "glyph_rasterizer/gecko"]
+gecko = ["firefox-on-glean", "glean", "glyph_rasterizer/gecko"]
sw_compositor = ["swgl"]
[build-dependencies]
build-parallel = "0.1.2"
-glslopt = "0.1.9"
+glslopt = "0.1.10"
webrender_build = { version = "0.0.2", path = "../webrender_build" }
[dependencies]
@@ -52,7 +52,7 @@ svg_fmt = "0.4"
tracy-rs = "0.1.2"
derive_more = { version = "0.99", default-features = false, features = ["add_assign"] }
etagere = "0.2.6"
-glean = "57.0.0"
+glean = { version = "58.1.0", optional = true }
firefox-on-glean = { version = "0.1.0", optional = true }
swgl = { path = "../swgl", optional = true }
topological-sort = "0.1"
diff --git a/gfx/wr/webrender/res/brush.glsl b/gfx/wr/webrender/res/brush.glsl
index 8d0d52ce82..67c9255831 100644
--- a/gfx/wr/webrender/res/brush.glsl
+++ b/gfx/wr/webrender/res/brush.glsl
@@ -214,7 +214,7 @@ void main(void) {
Instance instance = decode_instance_attributes();
PrimitiveHeader ph = fetch_prim_header(instance.prim_header_address);
Transform transform = fetch_transform(ph.transform_id);
- PictureTask task = fetch_picture_task(instance.picture_task_address);
+ PictureTask task = fetch_picture_task(ph.picture_task_address);
ClipArea clip_area = fetch_clip_area(instance.clip_address);
WR_VERTEX_SHADER_MAIN_FUNCTION(instance, ph, transform, task, clip_area);
diff --git a/gfx/wr/webrender/res/brush_linear_gradient.glsl b/gfx/wr/webrender/res/brush_linear_gradient.glsl
index ceb1b14e5b..235be4b24b 100644
--- a/gfx/wr/webrender/res/brush_linear_gradient.glsl
+++ b/gfx/wr/webrender/res/brush_linear_gradient.glsl
@@ -82,12 +82,12 @@ Fragment brush_fs() {
#ifdef SWGL_DRAW_SPAN
void swgl_drawSpanRGBA8() {
- int address = swgl_validateGradient(sGpuBuffer, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0));
+ int address = swgl_validateGradient(sGpuBufferF, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0));
if (address < 0) {
return;
}
- swgl_commitLinearGradientRGBA8(sGpuBuffer, address, GRADIENT_ENTRIES, true, v_gradient_repeat.x != 0.0,
+ swgl_commitLinearGradientRGBA8(sGpuBufferF, address, GRADIENT_ENTRIES, true, v_gradient_repeat.x != 0.0,
v_pos, v_scale_dir, v_start_offset.x);
}
#endif
diff --git a/gfx/wr/webrender/res/cs_border_segment.glsl b/gfx/wr/webrender/res/cs_border_segment.glsl
index e684bfa6df..7deb62f6ef 100644
--- a/gfx/wr/webrender/res/cs_border_segment.glsl
+++ b/gfx/wr/webrender/res/cs_border_segment.glsl
@@ -13,7 +13,7 @@ flat varying mediump vec4 vColor11;
// A point + tangent defining the line where the edge
// transition occurs. Used for corners only.
-flat varying mediump vec4 vColorLine;
+flat varying highp vec4 vColorLine;
// x: segment, y: clip mode
// We cast these to/from floats rather than using an ivec due to a driver bug
@@ -31,13 +31,13 @@ flat varying highp vec4 vClipCenter_Sign;
// An outer and inner elliptical radii for border
// corner clipping.
-flat varying mediump vec4 vClipRadii;
+flat varying highp vec4 vClipRadii;
// Reference point for determine edge clip lines.
-flat varying mediump vec4 vEdgeReference;
+flat varying highp vec4 vEdgeReference;
// Stores widths/2 and widths/3 to save doing this in FS.
-flat varying mediump vec4 vPartialWidths;
+flat varying highp vec4 vPartialWidths;
// Clipping parameters for dot or dash.
flat varying mediump vec4 vClipParams1;
diff --git a/gfx/wr/webrender/res/cs_clip_image.glsl b/gfx/wr/webrender/res/cs_clip_image.glsl
deleted file mode 100644
index 24ba1dab8e..0000000000
--- a/gfx/wr/webrender/res/cs_clip_image.glsl
+++ /dev/null
@@ -1,117 +0,0 @@
-/* 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/. */
-
-#include shared,clip_shared
-
-varying highp vec2 vLocalPos;
-varying highp vec2 vClipMaskImageUv;
-
-flat varying highp vec4 vClipMaskUvInnerRect;
-
-#ifdef WR_VERTEX_SHADER
-
-PER_INSTANCE in vec4 aClipTileRect;
-PER_INSTANCE in ivec2 aClipDataResourceAddress;
-PER_INSTANCE in vec4 aClipLocalRect;
-
-struct ClipMaskInstanceImage {
- ClipMaskInstanceCommon base;
- RectWithEndpoint tile_rect;
- ivec2 resource_address;
- RectWithEndpoint local_rect;
-};
-
-ClipMaskInstanceImage fetch_clip_item() {
- ClipMaskInstanceImage cmi;
-
- cmi.base = fetch_clip_item_common();
-
- cmi.tile_rect = RectWithEndpoint(aClipTileRect.xy, aClipTileRect.zw);
- cmi.resource_address = aClipDataResourceAddress;
- cmi.local_rect = RectWithEndpoint(aClipLocalRect.xy, aClipLocalRect.zw);
-
- return cmi;
-}
-
-struct ClipImageVertexInfo {
- vec2 local_pos;
- vec4 world_pos;
-};
-
-// This differs from write_clip_tile_vertex in that we forward transform the
-// primitive's local-space tile rect into the target space. We use scissoring
-// to ensure that the primitive does not draw outside the target bounds.
-ClipImageVertexInfo write_clip_image_vertex(RectWithEndpoint tile_rect,
- RectWithEndpoint local_clip_rect,
- Transform prim_transform,
- Transform clip_transform,
- RectWithEndpoint sub_rect,
- vec2 task_origin,
- vec2 screen_origin,
- float device_pixel_scale) {
- vec2 local_pos = rect_clamp(local_clip_rect, mix(tile_rect.p0, tile_rect.p1, aPosition.xy));
- vec4 world_pos = prim_transform.m * vec4(local_pos, 0.0, 1.0);
- vec4 final_pos = vec4(
- world_pos.xy * device_pixel_scale + (task_origin - screen_origin) * world_pos.w,
- 0.0,
- world_pos.w
- );
- gl_Position = uTransform * final_pos;
-
- init_transform_vs(
- clip_transform.is_axis_aligned
- ? vec4(vec2(-1.0e16), vec2(1.0e16))
- : vec4(local_clip_rect.p0, local_clip_rect.p1));
-
- ClipImageVertexInfo vi = ClipImageVertexInfo(local_pos, world_pos);
- return vi;
-}
-
-void main(void) {
- ClipMaskInstanceImage cmi = fetch_clip_item();
- Transform clip_transform = fetch_transform(cmi.base.clip_transform_id);
- Transform prim_transform = fetch_transform(cmi.base.prim_transform_id);
- ImageSource res = fetch_image_source_direct(cmi.resource_address);
-
- ClipImageVertexInfo vi = write_clip_image_vertex(
- cmi.tile_rect,
- cmi.local_rect,
- prim_transform,
- clip_transform,
- cmi.base.sub_rect,
- cmi.base.task_origin,
- cmi.base.screen_origin,
- cmi.base.device_pixel_scale
- );
- vLocalPos = vi.local_pos;
- vec2 uv = (vi.local_pos - cmi.tile_rect.p0) / rect_size(cmi.tile_rect);
-
- vec2 texture_size = vec2(TEX_SIZE(sColor0));
- vec4 uv_rect = vec4(res.uv_rect.p0, res.uv_rect.p1);
- vClipMaskImageUv = mix(uv_rect.xy, uv_rect.zw, uv) / texture_size;
-
- // applying a half-texel offset to the UV boundaries to prevent linear samples from the outside
- vClipMaskUvInnerRect = (uv_rect + vec4(0.5, 0.5, -0.5, -0.5)) / texture_size.xyxy;
-}
-#endif
-
-#ifdef WR_FRAGMENT_SHADER
-void main(void) {
- float alpha = init_transform_rough_fs(vLocalPos);
- vec2 source_uv = clamp(vClipMaskImageUv, vClipMaskUvInnerRect.xy, vClipMaskUvInnerRect.zw);
- float clip_alpha = texture(sColor0, source_uv).r; //careful: texture has type A8
- oFragColor = vec4(mix(1.0, clip_alpha, alpha), 0.0, 0.0, 1.0);
-}
-
-#ifdef SWGL_DRAW_SPAN
-void swgl_drawSpanR8() {
- if (has_valid_transform_bounds()) {
- return;
- }
-
- swgl_commitTextureLinearR8(sColor0, vClipMaskImageUv, vClipMaskUvInnerRect);
-}
-#endif
-
-#endif
diff --git a/gfx/wr/webrender/res/cs_linear_gradient.glsl b/gfx/wr/webrender/res/cs_linear_gradient.glsl
index b1aff899a6..1afee5818b 100644
--- a/gfx/wr/webrender/res/cs_linear_gradient.glsl
+++ b/gfx/wr/webrender/res/cs_linear_gradient.glsl
@@ -54,12 +54,12 @@ void main(void) {
#ifdef SWGL_DRAW_SPAN
void swgl_drawSpanRGBA8() {
- int address = swgl_validateGradient(sGpuBuffer, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0));
+ int address = swgl_validateGradient(sGpuBufferF, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0));
if (address < 0) {
return;
}
- swgl_commitLinearGradientRGBA8(sGpuBuffer, address, GRADIENT_ENTRIES, false, v_gradient_repeat.x != 0.0,
+ swgl_commitLinearGradientRGBA8(sGpuBufferF, address, GRADIENT_ENTRIES, false, v_gradient_repeat.x != 0.0,
v_pos, v_scale_dir, v_start_offset.x);
}
#endif
diff --git a/gfx/wr/webrender/res/cs_radial_gradient.glsl b/gfx/wr/webrender/res/cs_radial_gradient.glsl
index 16ffe06376..10919ac628 100644
--- a/gfx/wr/webrender/res/cs_radial_gradient.glsl
+++ b/gfx/wr/webrender/res/cs_radial_gradient.glsl
@@ -58,12 +58,12 @@ void main(void) {
#ifdef SWGL_DRAW_SPAN
void swgl_drawSpanRGBA8() {
- int address = swgl_validateGradient(sGpuBuffer, get_gpu_buffer_uv(v_gradient_address.x),
+ int address = swgl_validateGradient(sGpuBufferF, get_gpu_buffer_uv(v_gradient_address.x),
int(GRADIENT_ENTRIES + 2.0));
if (address < 0) {
return;
}
- swgl_commitRadialGradientRGBA8(sGpuBuffer, address, GRADIENT_ENTRIES, v_gradient_repeat.x != 0.0,
+ swgl_commitRadialGradientRGBA8(sGpuBufferF, address, GRADIENT_ENTRIES, v_gradient_repeat.x != 0.0,
v_pos, v_start_radius.x);
}
#endif
diff --git a/gfx/wr/webrender/res/gpu_buffer.glsl b/gfx/wr/webrender/res/gpu_buffer.glsl
index 25f4622db2..4923a28ef9 100644
--- a/gfx/wr/webrender/res/gpu_buffer.glsl
+++ b/gfx/wr/webrender/res/gpu_buffer.glsl
@@ -2,41 +2,47 @@
* 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/. */
-uniform HIGHP_SAMPLER_FLOAT sampler2D sGpuBuffer;
+uniform HIGHP_SAMPLER_FLOAT sampler2D sGpuBufferF;
+uniform HIGHP_SAMPLER_FLOAT isampler2D sGpuBufferI;
ivec2 get_gpu_buffer_uv(HIGHP_FS_ADDRESS int address) {
return ivec2(uint(address) % WR_MAX_VERTEX_TEXTURE_WIDTH,
uint(address) / WR_MAX_VERTEX_TEXTURE_WIDTH);
}
-vec4 fetch_from_gpu_buffer_1(HIGHP_FS_ADDRESS int address) {
+vec4 fetch_from_gpu_buffer_1f(HIGHP_FS_ADDRESS int address) {
ivec2 uv = get_gpu_buffer_uv(address);
- return texelFetch(sGpuBuffer, uv, 0);
+ return texelFetch(sGpuBufferF, uv, 0);
}
-vec4[2] fetch_from_gpu_buffer_2(HIGHP_FS_ADDRESS int address) {
+vec4[2] fetch_from_gpu_buffer_2f(HIGHP_FS_ADDRESS int address) {
ivec2 uv = get_gpu_buffer_uv(address);
return vec4[2](
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(0, 0)),
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(1, 0))
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)),
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0))
);
}
-vec4[3] fetch_from_gpu_buffer_3(HIGHP_FS_ADDRESS int address) {
+vec4[3] fetch_from_gpu_buffer_3f(HIGHP_FS_ADDRESS int address) {
ivec2 uv = get_gpu_buffer_uv(address);
return vec4[3](
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(0, 0)),
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(1, 0)),
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(2, 0))
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)),
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)),
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(2, 0))
);
}
-vec4[4] fetch_from_gpu_buffer_4(HIGHP_FS_ADDRESS int address) {
+vec4[4] fetch_from_gpu_buffer_4f(HIGHP_FS_ADDRESS int address) {
ivec2 uv = get_gpu_buffer_uv(address);
return vec4[4](
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(0, 0)),
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(1, 0)),
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(2, 0)),
- TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(3, 0))
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)),
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)),
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(2, 0)),
+ TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(3, 0))
);
}
+
+ivec4 fetch_from_gpu_buffer_1i(HIGHP_FS_ADDRESS int address) {
+ ivec2 uv = get_gpu_buffer_uv(address);
+ return texelFetch(sGpuBufferI, uv, 0);
+}
diff --git a/gfx/wr/webrender/res/gradient.glsl b/gfx/wr/webrender/res/gradient.glsl
index 87c011fefc..6ed2e69871 100644
--- a/gfx/wr/webrender/res/gradient.glsl
+++ b/gfx/wr/webrender/res/gradient.glsl
@@ -54,7 +54,7 @@ vec4 sample_gradient(float offset) {
float entry_fract = x - entry_index;
// Fetch the start and end color. There is a [start, end] color per entry.
- vec4 texels[2] = fetch_from_gpu_buffer_2(v_gradient_address.x + 2 * int(entry_index));
+ vec4 texels[2] = fetch_from_gpu_buffer_2f(v_gradient_address.x + 2 * int(entry_index));
// Finally interpolate and apply dithering
return dither(texels[0] + texels[1] * entry_fract);
diff --git a/gfx/wr/webrender/res/prim_shared.glsl b/gfx/wr/webrender/res/prim_shared.glsl
index 1a599bf980..9762658776 100644
--- a/gfx/wr/webrender/res/prim_shared.glsl
+++ b/gfx/wr/webrender/res/prim_shared.glsl
@@ -44,7 +44,6 @@ PER_INSTANCE in ivec4 aData;
struct Instance
{
int prim_header_address;
- int picture_task_address;
int clip_address;
int segment_index;
int flags;
@@ -56,8 +55,7 @@ Instance decode_instance_attributes() {
Instance instance;
instance.prim_header_address = aData.x;
- instance.picture_task_address = aData.y >> 16;
- instance.clip_address = aData.y & 0xffff;
+ instance.clip_address = aData.y;
instance.segment_index = aData.z & 0xffff;
instance.flags = aData.z >> 16;
instance.resource_address = aData.w & 0xffffff;
@@ -72,6 +70,7 @@ struct PrimitiveHeader {
float z;
int specific_prim_address;
int transform_id;
+ int picture_task_address;
ivec4 user_data;
};
@@ -90,6 +89,7 @@ PrimitiveHeader fetch_prim_header(int index) {
ph.z = float(data0.x);
ph.specific_prim_address = data0.y;
ph.transform_id = data0.z;
+ ph.picture_task_address = data0.w;
ph.user_data = data1;
return ph;
diff --git a/gfx/wr/webrender/res/ps_quad.glsl b/gfx/wr/webrender/res/ps_quad.glsl
index ed6b35c3b8..94c80a93f7 100644
--- a/gfx/wr/webrender/res/ps_quad.glsl
+++ b/gfx/wr/webrender/res/ps_quad.glsl
@@ -2,12 +2,40 @@
* 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/. */
+/// The common infrastructure for ps_quad_* shaders.
+///
+/// # Memory layout
+///
+/// The diagram below shows the the various pieces of data fectched in the vertex shader:
+///
+///```ascii
+/// (int gpu buffer)
+/// +---------------+ (sGpuCache)
+/// (instance-step vertex attr) | Int header | +-----------+
+/// +-----------------------------+ | | | Transform |
+/// | Quad instance (uvec4) | +--> | transform id +--> +-----------+
+/// | | | | z id |
+/// | x: int prim address +---+ +---------------+ (float gpu buffer)
+/// | y: float prim address +--------------------------> +-----------+--------------+-+-+
+/// | z: quad flags | (sGpuCache) | Quad Prim | Quad Segment | | |
+/// | edge flags | +--------------------+ | | | | |
+/// | part index | | Picture task | | bounds | rect | | |
+/// | segment index | | | | clip | uv rect | | |
+/// | w: picture task address +--> | task rect | | color | | | |
+/// +-----------------------------+ | device pixel scale | +-----------+--------------+-+-+
+/// | content origin |
+/// +--------------------+
+///```
+
#define WR_FEATURE_TEXTURE_2D
#include shared,rect,transform,render_task,gpu_buffer
flat varying mediump vec4 v_color;
flat varying mediump vec4 v_uv_sample_bounds;
+// x: (in ps_quad_textured) has edge flags
+// y: has uv rect
+// z: (in ps_quad_textured) sample as mask
flat varying lowp ivec4 v_flags;
varying highp vec2 v_uv;
@@ -61,7 +89,7 @@ struct QuadPrimitive {
QuadSegment fetch_segment(int base, int index) {
QuadSegment seg;
- vec4 texels[2] = fetch_from_gpu_buffer_2(base + 3 + index * 2);
+ vec4 texels[2] = fetch_from_gpu_buffer_2f(base + 3 + index * 2);
seg.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
seg.uv_rect = texels[1];
@@ -72,7 +100,7 @@ QuadSegment fetch_segment(int base, int index) {
QuadPrimitive fetch_primitive(int index) {
QuadPrimitive prim;
- vec4 texels[3] = fetch_from_gpu_buffer_3(index);
+ vec4 texels[3] = fetch_from_gpu_buffer_3f(index);
prim.bounds = RectWithEndpoint(texels[0].xy, texels[0].zw);
prim.clip = RectWithEndpoint(texels[1].xy, texels[1].zw);
@@ -81,37 +109,51 @@ QuadPrimitive fetch_primitive(int index) {
return prim;
}
+struct QuadHeader {
+ int transform_id;
+ int z_id;
+};
+
+QuadHeader fetch_header(int address) {
+ ivec4 header = fetch_from_gpu_buffer_1i(address);
+
+ QuadHeader qh = QuadHeader(
+ header.x,
+ header.y
+ );
+
+ return qh;
+}
+
struct QuadInstance {
// x
- int prim_address;
+ int prim_address_i;
// y
- int quad_flags;
- int edge_flags;
- int picture_task_address;
+ int prim_address_f;
// z
+ int quad_flags;
+ int edge_flags;
int part_index;
- int z_id;
+ int segment_index;
// w
- int segment_index;
- int transform_id;
+ int picture_task_address;
};
QuadInstance decode_instance() {
QuadInstance qi = QuadInstance(
aData.x,
- (aData.y >> 24) & 0xff,
- (aData.y >> 16) & 0xff,
- aData.y & 0xffff,
+ aData.y,
(aData.z >> 24) & 0xff,
- aData.z & 0xffffff,
+ (aData.z >> 16) & 0xff,
+ (aData.z >> 8) & 0xff,
+ (aData.z >> 0) & 0xff,
- (aData.w >> 24) & 0xff,
- aData.w & 0xffffff
+ aData.w
);
return qi;
@@ -165,17 +207,18 @@ float edge_aa_offset(int edge, int flags) {
PrimitiveInfo ps_quad_main(void) {
QuadInstance qi = decode_instance();
- Transform transform = fetch_transform(qi.transform_id);
+ QuadHeader qh = fetch_header(qi.prim_address_i);
+ Transform transform = fetch_transform(qh.transform_id);
PictureTask task = fetch_picture_task(qi.picture_task_address);
- QuadPrimitive prim = fetch_primitive(qi.prim_address);
- float z = float(qi.z_id);
+ QuadPrimitive prim = fetch_primitive(qi.prim_address_f);
+ float z = float(qh.z_id);
QuadSegment seg;
if (qi.segment_index == INVALID_SEGMENT_INDEX) {
seg.rect = prim.bounds;
seg.uv_rect = vec4(0.0);
} else {
- seg = fetch_segment(qi.prim_address, qi.segment_index);
+ seg = fetch_segment(qi.prim_address_f, qi.segment_index);
}
// The local space rect that we will draw, which is effectively:
diff --git a/gfx/wr/webrender/res/ps_quad_mask.glsl b/gfx/wr/webrender/res/ps_quad_mask.glsl
index 4b28109726..6b72714efb 100644
--- a/gfx/wr/webrender/res/ps_quad_mask.glsl
+++ b/gfx/wr/webrender/res/ps_quad_mask.glsl
@@ -2,6 +2,8 @@
* 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/. */
+/// This shader applies a (rounded) rectangle mask to the content of the framebuffer.
+
#include ps_quad,ellipse
varying highp vec4 vClipLocalPos;
@@ -45,12 +47,12 @@ Clip fetch_clip(int index) {
clip.space = aClipData.z;
#ifdef WR_FEATURE_FAST_PATH
- vec4 texels[3] = fetch_from_gpu_buffer_3(index);
+ vec4 texels[3] = fetch_from_gpu_buffer_3f(index);
clip.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
clip.radii = texels[1];
clip.mode = texels[2].x;
#else
- vec4 texels[4] = fetch_from_gpu_buffer_4(index);
+ vec4 texels[4] = fetch_from_gpu_buffer_4f(index);
clip.rect = RectWithEndpoint(texels[0].xy, texels[0].zw);
clip.radii_top = texels[1];
clip.radii_bottom = texels[2];
diff --git a/gfx/wr/webrender/res/ps_quad_textured.glsl b/gfx/wr/webrender/res/ps_quad_textured.glsl
index 48579eb4fe..2382623cdb 100644
--- a/gfx/wr/webrender/res/ps_quad_textured.glsl
+++ b/gfx/wr/webrender/res/ps_quad_textured.glsl
@@ -2,6 +2,8 @@
* 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/. */
+/// This shader renders solid colors or simple images in a color or alpha target.
+
#include ps_quad
#ifndef SWGL_ANTIALIAS
diff --git a/gfx/wr/webrender/res/ps_text_run.glsl b/gfx/wr/webrender/res/ps_text_run.glsl
index aabc1e9d8a..9faac99620 100644
--- a/gfx/wr/webrender/res/ps_text_run.glsl
+++ b/gfx/wr/webrender/res/ps_text_run.glsl
@@ -100,7 +100,7 @@ void main() {
PrimitiveHeader ph = fetch_prim_header(instance.prim_header_address);
Transform transform = fetch_transform(ph.transform_id);
ClipArea clip_area = fetch_clip_area(instance.clip_address);
- PictureTask task = fetch_picture_task(instance.picture_task_address);
+ PictureTask task = fetch_picture_task(ph.picture_task_address);
int glyph_index = instance.segment_index;
int subpx_dir = (instance.flags >> 8) & 0xff;
diff --git a/gfx/wr/webrender/res/render_task.glsl b/gfx/wr/webrender/res/render_task.glsl
index cd9aea402c..e5d0c298cd 100644
--- a/gfx/wr/webrender/res/render_task.glsl
+++ b/gfx/wr/webrender/res/render_task.glsl
@@ -73,7 +73,7 @@ PictureTask fetch_picture_task(int address) {
return task;
}
-#define CLIP_TASK_EMPTY 0x7FFF
+#define CLIP_TASK_EMPTY 0x7FFFFFFF
struct ClipArea {
RectWithEndpoint task_rect;
@@ -82,21 +82,22 @@ struct ClipArea {
};
ClipArea fetch_clip_area(int index) {
- ClipArea area;
-
+ RenderTaskData task_data;
if (index >= CLIP_TASK_EMPTY) {
- area.task_rect = RectWithEndpoint(vec2(0.0), vec2(0.0));
- area.device_pixel_scale = 0.0;
- area.screen_origin = vec2(0.0);
+ // We deliberately create a dummy RenderTaskData here then convert to a
+ // ClipArea after this if-else statement, rather than initialize the
+ // ClipArea in separate branches, to avoid a miscompile in some Adreno
+ // drivers. See bug 1884791. Unfortunately the specific details of the bug
+ // are unknown, so please take extra care not to regress this when
+ // refactoring.
+ task_data = RenderTaskData(RectWithEndpoint(vec2(0.0), vec2(0.0)),
+ vec4(0.0));
} else {
- RenderTaskData task_data = fetch_render_task_data(index);
-
- area.task_rect = task_data.task_rect;
- area.device_pixel_scale = task_data.user_data.x;
- area.screen_origin = task_data.user_data.yz;
+ task_data = fetch_render_task_data(index);
}
- return area;
+ return ClipArea(task_data.task_rect, task_data.user_data.x,
+ task_data.user_data.yz);
}
#endif //WR_VERTEX_SHADER
diff --git a/gfx/wr/webrender/src/batch.rs b/gfx/wr/webrender/src/batch.rs
index f39b60acc6..605283c58d 100644
--- a/gfx/wr/webrender/src/batch.rs
+++ b/gfx/wr/webrender/src/batch.rs
@@ -16,7 +16,7 @@ use crate::gpu_types::{SplitCompositeInstance, QuadInstance};
use crate::gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance};
use crate::gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette};
use crate::gpu_types::{ImageBrushData, get_shader_opacity, BoxShadowData, MaskInstance};
-use crate::gpu_types::{ClipMaskInstanceCommon, ClipMaskInstanceImage, ClipMaskInstanceRect, ClipMaskInstanceBoxShadow};
+use crate::gpu_types::{ClipMaskInstanceCommon, ClipMaskInstanceRect, ClipMaskInstanceBoxShadow};
use crate::internal_types::{FastHashMap, Swizzle, TextureSource, Filter};
use crate::picture::{Picture3DContext, PictureCompositeMode, calculate_screen_uv};
use crate::prim_store::{PrimitiveInstanceKind, ClipData};
@@ -26,8 +26,8 @@ use crate::prim_store::{VECS_PER_SEGMENT, PrimitiveInstanceIndex};
use crate::render_target::RenderTargetContext;
use crate::render_task_graph::{RenderTaskId, RenderTaskGraph};
use crate::render_task::{RenderTaskAddress, RenderTaskKind, SubPass};
-use crate::renderer::{BlendMode, ShaderColorMode};
-use crate::renderer::{MAX_VERTEX_TEXTURE_WIDTH, GpuBufferBuilder, GpuBufferAddress};
+use crate::renderer::{BlendMode, GpuBufferBuilder, ShaderColorMode};
+use crate::renderer::{MAX_VERTEX_TEXTURE_WIDTH, GpuBufferAddress};
use crate::resource_cache::{GlyphFetchResult, ImageProperties};
use crate::space::SpaceMapper;
use crate::visibility::{PrimitiveVisibilityFlags, VisibilityState};
@@ -38,7 +38,7 @@ use crate::segment::EdgeAaSegmentMask;
// Special sentinel value recognized by the shader. It is considered to be
// a dummy task that doesn't mask out anything.
-const OPAQUE_TASK_ADDRESS: RenderTaskAddress = RenderTaskAddress(0x7fff);
+const OPAQUE_TASK_ADDRESS: RenderTaskAddress = RenderTaskAddress(0x7fffffff);
/// Used to signal there are no segments provided with this primitive.
pub const INVALID_SEGMENT_INDEX: i32 = 0xffff;
@@ -745,13 +745,10 @@ impl BatchBuilder {
prim_header_index: PrimitiveHeaderIndex,
resource_address: i32,
) {
- let render_task_address = self.batcher.render_task_address;
-
let instance = BrushInstance {
segment_index,
edge_flags,
clip_task_address,
- render_task_address,
brush_flags,
prim_header_index,
resource_address,
@@ -803,7 +800,7 @@ impl BatchBuilder {
&mut self,
prim_instance_index: PrimitiveInstanceIndex,
transform_id: TransformPaletteId,
- gpu_buffer_address: GpuBufferAddress,
+ prim_address_f: GpuBufferAddress,
quad_flags: QuadFlags,
edge_flags: EdgeAaSegmentMask,
segment_index: u8,
@@ -811,6 +808,7 @@ impl BatchBuilder {
z_generator: &mut ZBufferIdGenerator,
prim_instances: &[PrimitiveInstance],
render_tasks: &RenderTaskGraph,
+ gpu_buffer_builder: &mut GpuBufferBuilder,
) {
let prim_instance = &prim_instances[prim_instance_index.0 as usize];
let prim_info = &prim_instance.vis;
@@ -820,13 +818,14 @@ impl BatchBuilder {
add_quad_to_batch(
self.batcher.render_task_address,
transform_id,
- gpu_buffer_address,
+ prim_address_f,
quad_flags,
edge_flags,
segment_index,
task_id,
z_id,
render_tasks,
+ gpu_buffer_builder,
|key, instance| {
let batch = self.batcher.set_params_and_get_batch(
key,
@@ -857,7 +856,7 @@ impl BatchBuilder {
surface_spatial_node_index: SpatialNodeIndex,
z_generator: &mut ZBufferIdGenerator,
prim_instances: &[PrimitiveInstance],
- _gpu_buffer_builder: &mut GpuBufferBuilder,
+ gpu_buffer_builder: &mut GpuBufferBuilder,
segments: &[RenderTaskId],
) {
let (prim_instance_index, extra_prim_gpu_address) = match cmd {
@@ -883,6 +882,7 @@ impl BatchBuilder {
z_generator,
prim_instances,
render_tasks,
+ gpu_buffer_builder,
);
} else {
for (i, task_id) in segments.iter().enumerate() {
@@ -900,6 +900,7 @@ impl BatchBuilder {
z_generator,
prim_instances,
render_tasks,
+ gpu_buffer_builder,
);
}
}
@@ -1005,6 +1006,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
[get_shader_opacity(1.0), 0, 0, 0],
);
@@ -1083,6 +1085,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -1137,6 +1140,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
[
(run.raster_scale * 65535.0).round() as i32,
0,
@@ -1312,7 +1316,6 @@ impl BatchBuilder {
let key = BatchKey::new(kind, blend_mode, textures);
- let render_task_address = batcher.render_task_address;
let batch = batcher.alpha_batch_list.set_params_and_get_batch(
key,
batch_features,
@@ -1323,7 +1326,6 @@ impl BatchBuilder {
batch.reserve(glyphs.len());
for glyph in glyphs {
batch.push(base_instance.build(
- render_task_address,
clip_task_address,
subpx_dir,
glyph.index_in_text_run,
@@ -1397,6 +1399,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
prim_user_data,
);
@@ -1531,6 +1534,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
ImageBrushData {
color_mode: ShaderColorMode::Image,
alpha_type: AlphaType::PremultipliedAlpha,
@@ -1616,6 +1620,7 @@ impl BatchBuilder {
let shadow_prim_header_index = prim_headers.push(
&shadow_prim_header,
z_id,
+ self.batcher.render_task_address,
ImageBrushData {
color_mode: ShaderColorMode::Alpha,
alpha_type: AlphaType::PremultipliedAlpha,
@@ -1642,6 +1647,7 @@ impl BatchBuilder {
let content_prim_header_index = prim_headers.push(
&prim_header,
z_id_content,
+ self.batcher.render_task_address,
ImageBrushData {
color_mode: ShaderColorMode::Image,
alpha_type: AlphaType::PremultipliedAlpha,
@@ -1687,12 +1693,17 @@ impl BatchBuilder {
textures,
);
- let prim_header_index = prim_headers.push(&prim_header, z_id, [
- uv_rect_address.as_int(),
- amount,
- 0,
- 0,
- ]);
+ let prim_header_index = prim_headers.push(
+ &prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ [
+ uv_rect_address.as_int(),
+ amount,
+ 0,
+ 0,
+ ]
+ );
self.add_brush_instance_to_batches(
key,
@@ -1771,12 +1782,17 @@ impl BatchBuilder {
textures,
);
- let prim_header_index = prim_headers.push(&prim_header, z_id, [
- uv_rect_address.as_int(),
- filter_mode,
- user_data,
- 0,
- ]);
+ let prim_header_index = prim_headers.push(
+ &prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ [
+ uv_rect_address.as_int(),
+ filter_mode,
+ user_data,
+ 0,
+ ]
+ );
self.add_brush_instance_to_batches(
key,
@@ -1826,12 +1842,17 @@ impl BatchBuilder {
textures,
);
- let prim_header_index = prim_headers.push(&prim_header, z_id, [
- uv_rect_address.as_int(),
- filter_mode,
- user_data,
- 0,
- ]);
+ let prim_header_index = prim_headers.push(
+ &prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ [
+ uv_rect_address.as_int(),
+ filter_mode,
+ user_data,
+ 0,
+ ]
+ );
self.add_brush_instance_to_batches(
key,
@@ -1882,6 +1903,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
ImageBrushData {
color_mode: match key.blend_mode {
BlendMode::MultiplyDualSource => ShaderColorMode::MultiplyDualSource,
@@ -1924,8 +1946,6 @@ impl BatchBuilder {
// and allow mix-blends to operate on picture cache surfaces without
// a separate isolated intermediate surface.
- let render_task_address = self.batcher.render_task_address;
-
let batch_key = BatchKey::new(
BatchKind::Brush(
BrushBatchKind::MixBlend {
@@ -1953,18 +1973,22 @@ impl BatchBuilder {
);
let src_uv_address = render_tasks[pic_task_id].get_texture_address(gpu_cache);
let readback_uv_address = render_tasks[backdrop_id].get_texture_address(gpu_cache);
- let prim_header_index = prim_headers.push(&prim_header, z_id, [
- mode as u32 as i32,
- readback_uv_address.as_int(),
- src_uv_address.as_int(),
- 0,
- ]);
+ let prim_header_index = prim_headers.push(
+ &prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ [
+ mode as u32 as i32,
+ readback_uv_address.as_int(),
+ src_uv_address.as_int(),
+ 0,
+ ]
+ );
let instance = BrushInstance {
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::all(),
clip_task_address,
- render_task_address,
brush_flags,
prim_header_index,
resource_address: 0,
@@ -2030,12 +2054,17 @@ impl BatchBuilder {
// by this inner loop.
let z_id = z_generator.next();
- let prim_header_index = prim_headers.push(&prim_header, z_id, [
- uv_rect_address.as_int(),
- BrushFlags::PERSPECTIVE_INTERPOLATION.bits() as i32,
- 0,
- child_clip_task_address.0 as i32,
- ]);
+ let prim_header_index = prim_headers.push(
+ &prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ [
+ uv_rect_address.as_int(),
+ BrushFlags::PERSPECTIVE_INTERPOLATION.bits() as i32,
+ 0,
+ child_clip_task_address.0 as i32,
+ ]
+ );
let key = BatchKey::new(
BatchKind::SplitComposite,
@@ -2088,6 +2117,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -2141,6 +2171,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
ImageBrushData {
color_mode: ShaderColorMode::Image,
alpha_type: AlphaType::PremultipliedAlpha,
@@ -2215,6 +2246,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -2274,6 +2306,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -2394,6 +2427,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -2498,6 +2532,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -2547,7 +2582,12 @@ impl BatchBuilder {
specific_prim_address: gpu_cache.get_address(&gpu_handle),
transform_id,
};
- let prim_header_index = prim_headers.push(&prim_header, z_id, prim_user_data);
+ let prim_header_index = prim_headers.push(
+ &prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ prim_user_data,
+ );
for (i, tile) in chunk.iter().enumerate() {
let (uv_rect_address, texture) = match render_tasks.resolve_location(tile.src_color, gpu_cache) {
@@ -2616,7 +2656,12 @@ impl BatchBuilder {
prim_header.specific_prim_address = gpu_cache.get_address(&prim_data.gpu_cache_handle);
- let prim_header_index = prim_headers.push(&prim_header, z_id, user_data);
+ let prim_header_index = prim_headers.push(
+ &prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ user_data,
+ );
let segments = if prim_data.brush_segments.is_empty() {
None
@@ -2660,7 +2705,12 @@ impl BatchBuilder {
local_clip_rect: tile.local_clip_rect,
..prim_header
};
- let prim_header_index = prim_headers.push(&tile_prim_header, z_id, user_data);
+ let prim_header_index = prim_headers.push(
+ &tile_prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ user_data,
+ );
self.add_brush_instance_to_batches(
key,
@@ -2735,6 +2785,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -2777,7 +2828,12 @@ impl BatchBuilder {
local_clip_rect: tile.local_clip_rect,
..prim_header
};
- let prim_header_index = prim_headers.push(&tile_prim_header, z_id, prim_user_data);
+ let prim_header_index = prim_headers.push(
+ &tile_prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ prim_user_data,
+ );
self.add_brush_instance_to_batches(
batch_key,
@@ -2853,6 +2909,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -2895,7 +2952,12 @@ impl BatchBuilder {
local_clip_rect: tile.local_clip_rect,
..prim_header
};
- let prim_header_index = prim_headers.push(&tile_prim_header, z_id, prim_user_data);
+ let prim_header_index = prim_headers.push(
+ &tile_prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ prim_user_data,
+ );
self.add_brush_instance_to_batches(
batch_key,
@@ -2972,6 +3034,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
batch_params.prim_user_data,
);
@@ -3014,7 +3077,12 @@ impl BatchBuilder {
local_clip_rect: tile.local_clip_rect,
..prim_header
};
- let prim_header_index = prim_headers.push(&tile_prim_header, z_id, prim_user_data);
+ let prim_header_index = prim_headers.push(
+ &tile_prim_header,
+ z_id,
+ self.batcher.render_task_address,
+ prim_user_data,
+ );
self.add_brush_instance_to_batches(
batch_key,
@@ -3068,6 +3136,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
ImageBrushData {
color_mode: ShaderColorMode::Image,
alpha_type: AlphaType::PremultipliedAlpha,
@@ -3179,6 +3248,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
+ self.batcher.render_task_address,
[get_shader_opacity(1.0), 0, 0, 0],
);
@@ -3477,8 +3547,6 @@ pub struct ClipBatchList {
/// Rectangle draws fill up the rectangles with rounded corners.
pub slow_rectangles: Vec<ClipMaskInstanceRect>,
pub fast_rectangles: Vec<ClipMaskInstanceRect>,
- /// Image draws apply the image masking.
- pub images: FastHashMap<(TextureSource, Option<DeviceIntRect>), Vec<ClipMaskInstanceImage>>,
pub box_shadows: FastHashMap<TextureSource, Vec<ClipMaskInstanceBoxShadow>>,
}
@@ -3487,7 +3555,6 @@ impl ClipBatchList {
ClipBatchList {
slow_rectangles: Vec::new(),
fast_rectangles: Vec::new(),
- images: FastHashMap::default(),
box_shadows: FastHashMap::default(),
}
}
@@ -3674,20 +3741,11 @@ impl ClipBatcher {
ctx.spatial_tree,
);
- // For clip mask images, we need to map from the primitive's layout space to
- // the target space, as the cs_clip_image shader needs to forward transform
- // the local image bounds, rather than backwards transform the target bounds
- // as in done in write_clip_tile_vertex.
- let prim_transform_id = match clip_node.item.kind {
- ClipItemKind::Image { .. } => { panic!("bug: old path not supported") }
- _ => {
- transforms.get_id(
- root_spatial_node_index,
- ctx.root_spatial_node_index,
- ctx.spatial_tree,
- )
- }
- };
+ let prim_transform_id = transforms.get_id(
+ root_spatial_node_index,
+ ctx.root_spatial_node_index,
+ ctx.spatial_tree,
+ );
let common = ClipMaskInstanceCommon {
sub_rect: DeviceRect::from_size(actual_rect.size()),
@@ -3837,13 +3895,14 @@ impl<'a, 'rc> RenderTargetContext<'a, 'rc> {
pub fn add_quad_to_batch<F>(
render_task_address: RenderTaskAddress,
transform_id: TransformPaletteId,
- gpu_buffer_address: GpuBufferAddress,
+ prim_address_f: GpuBufferAddress,
quad_flags: QuadFlags,
edge_flags: EdgeAaSegmentMask,
segment_index: u8,
task_id: RenderTaskId,
z_id: ZBufferId,
render_tasks: &RenderTaskGraph,
+ gpu_buffer_builder: &mut GpuBufferBuilder,
mut f: F,
) where F: FnMut(BatchKey, PrimitiveInstanceData) {
@@ -3857,6 +3916,15 @@ pub fn add_quad_to_batch<F>(
All = 5,
}
+ let mut writer = gpu_buffer_builder.i32.write_blocks(1);
+ writer.push_one([
+ transform_id.0 as i32,
+ z_id.0,
+ 0,
+ 0,
+ ]);
+ let prim_address_i = writer.finish();
+
let texture = match task_id {
RenderTaskId::INVALID => {
TextureSource::Invalid
@@ -3898,7 +3966,8 @@ pub fn add_quad_to_batch<F>(
if edge_flags.is_empty() {
let instance = QuadInstance {
render_task_address,
- prim_address: gpu_buffer_address,
+ prim_address_i,
+ prim_address_f,
z_id,
transform_id,
edge_flags: edge_flags_bits,
@@ -3911,7 +3980,8 @@ pub fn add_quad_to_batch<F>(
} else if quad_flags.contains(QuadFlags::USE_AA_SEGMENTS) {
let main_instance = QuadInstance {
render_task_address,
- prim_address: gpu_buffer_address,
+ prim_address_i,
+ prim_address_f,
z_id,
transform_id,
edge_flags: edge_flags_bits,
@@ -3956,7 +4026,8 @@ pub fn add_quad_to_batch<F>(
} else {
let instance = QuadInstance {
render_task_address,
- prim_address: gpu_buffer_address,
+ prim_address_i,
+ prim_address_f,
z_id,
transform_id,
edge_flags: edge_flags_bits,
diff --git a/gfx/wr/webrender/src/device/gl.rs b/gfx/wr/webrender/src/device/gl.rs
index 5ad9469185..04a7e13023 100644
--- a/gfx/wr/webrender/src/device/gl.rs
+++ b/gfx/wr/webrender/src/device/gl.rs
@@ -138,9 +138,13 @@ pub enum UploadMethod {
}
/// Plain old data that can be used to initialize a texture.
-pub unsafe trait Texel: Copy {}
-unsafe impl Texel for u8 {}
-unsafe impl Texel for f32 {}
+pub unsafe trait Texel: Copy + Default {
+ fn image_format() -> ImageFormat;
+}
+
+unsafe impl Texel for u8 {
+ fn image_format() -> ImageFormat { ImageFormat::R8 }
+}
/// Returns the size in bytes of a depth target with the given dimensions.
fn depth_target_size_in_bytes(dimensions: &DeviceIntSize) -> usize {
diff --git a/gfx/wr/webrender/src/frame_builder.rs b/gfx/wr/webrender/src/frame_builder.rs
index 4ff798c103..b975c960eb 100644
--- a/gfx/wr/webrender/src/frame_builder.rs
+++ b/gfx/wr/webrender/src/frame_builder.rs
@@ -25,7 +25,7 @@ use crate::prim_store::{PictureIndex, PrimitiveScratchBuffer};
use crate::prim_store::{DeferredResolve, PrimitiveInstance};
use crate::profiler::{self, TransactionProfile};
use crate::render_backend::{DataStores, ScratchBuffer};
-use crate::renderer::{GpuBuffer, GpuBufferBuilder};
+use crate::renderer::{GpuBufferF, GpuBufferBuilderF, GpuBufferI, GpuBufferBuilderI, GpuBufferBuilder};
use crate::render_target::{RenderTarget, PictureCacheTarget, TextureCacheRenderTarget, PictureCacheTargetKind};
use crate::render_target::{RenderTargetContext, RenderTargetKind, AlphaRenderTarget, ColorRenderTarget};
use crate::render_task_graph::{RenderTaskGraph, Pass, SubPassSurface};
@@ -558,7 +558,10 @@ impl FrameBuilder {
let mut cmd_buffers = CommandBufferList::new();
// TODO(gw): Recycle backing vec buffers for gpu buffer builder between frames
- let mut gpu_buffer_builder = GpuBufferBuilder::new();
+ let mut gpu_buffer_builder = GpuBufferBuilder {
+ f32: GpuBufferBuilderF::new(),
+ i32: GpuBufferBuilderI::new(),
+ };
self.build_layer_screen_rects_and_cull_layers(
scene,
@@ -690,7 +693,8 @@ impl FrameBuilder {
scene.clip_store.end_frame(&mut scratch.clip_store);
scratch.end_frame();
- let gpu_buffer = gpu_buffer_builder.finalize(&render_tasks);
+ let gpu_buffer_f = gpu_buffer_builder.f32.finalize(&render_tasks);
+ let gpu_buffer_i = gpu_buffer_builder.i32.finalize(&render_tasks);
Frame {
device_rect: DeviceIntRect::from_origin_and_size(
@@ -707,7 +711,8 @@ impl FrameBuilder {
prim_headers,
debug_items: mem::replace(&mut scratch.primitive.debug_items, Vec::new()),
composite_state,
- gpu_buffer,
+ gpu_buffer_f,
+ gpu_buffer_i,
}
}
@@ -759,7 +764,6 @@ impl FrameBuilder {
const LAYOUT_PORT_COLOR: ColorF = debug_colors::RED;
const VISUAL_PORT_COLOR: ColorF = debug_colors::BLUE;
const DISPLAYPORT_COLOR: ColorF = debug_colors::LIME;
- const NOTHING: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
let viewport = scroll_frame_info.viewport_rect;
@@ -805,9 +809,10 @@ impl FrameBuilder {
}
let mut add_rect = |rect, border, fill| -> Option<()> {
+ const STROKE_WIDTH: f32 = 2.0;
// Place rect in scroll frame's local coordinate space
let transformed_rect = transform.outer_transformed_box2d(&rect)?;
-
+
// Transform to world coordinates, using root-content coords as an intermediate step.
let mut root_content_rect = local_to_root_content.outer_transformed_box2d(&transformed_rect)?;
// In root-content coords, apply the root content node's viewport clip.
@@ -820,21 +825,28 @@ impl FrameBuilder {
}
let world_rect = root_content_to_world.outer_transformed_box2d(&root_content_rect)?;
+ scratch.push_debug_rect_with_stroke_width(world_rect, border, STROKE_WIDTH);
+
// Add world coordinate rects to scratch.debug_items
- // TODO: Add a parameter to control the border thickness of the rects, and make them a bit thicker.
- scratch.push_debug_rect(world_rect * DevicePixelScale::new(1.0), border, fill);
+ if let Some(fill_color) = fill {
+ let interior_world_rect = WorldRect::new(
+ world_rect.min + WorldVector2D::new(STROKE_WIDTH, STROKE_WIDTH),
+ world_rect.max - WorldVector2D::new(STROKE_WIDTH, STROKE_WIDTH)
+ );
+ scratch.push_debug_rect(interior_world_rect * DevicePixelScale::new(1.0), border, fill_color);
+ }
Some(())
};
- add_rect(minimap_data.scrollable_rect, PAGE_BORDER_COLOR, BACKGROUND_COLOR);
- add_rect(minimap_data.visual_viewport, VISUAL_PORT_COLOR, NOTHING);
- add_rect(minimap_data.displayport, DISPLAYPORT_COLOR, DISPLAYPORT_BACKGROUND_COLOR);
+ add_rect(minimap_data.scrollable_rect, PAGE_BORDER_COLOR, Some(BACKGROUND_COLOR));
+ add_rect(minimap_data.displayport, DISPLAYPORT_COLOR, Some(DISPLAYPORT_BACKGROUND_COLOR));
// Only render a distinct layout viewport for the root content.
// For other scroll frames, the visual and layout viewports coincide.
if minimap_data.is_root_content {
- add_rect(minimap_data.layout_viewport, LAYOUT_PORT_COLOR, NOTHING);
+ add_rect(minimap_data.layout_viewport, LAYOUT_PORT_COLOR, None);
}
+ add_rect(minimap_data.visual_viewport, VISUAL_PORT_COLOR, None);
}
}
});
@@ -967,7 +979,6 @@ pub fn build_render_pass(
let task_id = sub_pass.task_ids[0];
let task = &render_tasks[task_id];
let target_rect = task.get_target_rect();
- let mut gpu_buffer_builder = GpuBufferBuilder::new();
match task.kind {
RenderTaskKind::Picture(ref pic_task) => {
@@ -998,7 +1009,7 @@ pub fn build_render_pass(
pic_task.surface_spatial_node_index,
z_generator,
prim_instances,
- &mut gpu_buffer_builder,
+ gpu_buffer_builder,
segments,
);
});
@@ -1072,6 +1083,7 @@ pub fn build_render_pass(
z_generator,
prim_instances,
cmd_buffers,
+ gpu_buffer_builder,
);
pass.alpha.build(
ctx,
@@ -1082,6 +1094,7 @@ pub fn build_render_pass(
z_generator,
prim_instances,
cmd_buffers,
+ gpu_buffer_builder,
);
pass
@@ -1127,7 +1140,8 @@ pub struct Frame {
/// Main GPU data buffer constructed (primarily) during the prepare
/// pass for primitives that were visible and dirty.
- pub gpu_buffer: GpuBuffer,
+ pub gpu_buffer_f: GpuBufferF,
+ pub gpu_buffer_i: GpuBufferI,
}
impl Frame {
diff --git a/gfx/wr/webrender/src/gpu_types.rs b/gfx/wr/webrender/src/gpu_types.rs
index f6d24b2e39..e222ebed04 100644
--- a/gfx/wr/webrender/src/gpu_types.rs
+++ b/gfx/wr/webrender/src/gpu_types.rs
@@ -125,6 +125,7 @@ pub struct SvgFilterInstance {
pub kind: u16,
pub input_count: u16,
pub generic_int: u16,
+ pub padding: u16,
pub extra_data_address: GpuCacheAddress,
}
@@ -175,17 +176,6 @@ pub struct ClipMaskInstanceCommon {
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[repr(C)]
-pub struct ClipMaskInstanceImage {
- pub common: ClipMaskInstanceCommon,
- pub tile_rect: LayoutRect,
- pub resource_address: GpuCacheAddress,
- pub local_rect: LayoutRect,
-}
-
-#[derive(Clone, Debug)]
-#[cfg_attr(feature = "capture", derive(Serialize))]
-#[cfg_attr(feature = "replay", derive(Deserialize))]
-#[repr(C)]
pub struct ClipMaskInstanceRect {
pub common: ClipMaskInstanceCommon,
pub local_pos: LayoutPoint,
@@ -428,6 +418,7 @@ impl PrimitiveHeaders {
&mut self,
prim_header: &PrimitiveHeader,
z: ZBufferId,
+ render_task_address: RenderTaskAddress,
user_data: [i32; 4],
) -> PrimitiveHeaderIndex {
debug_assert_eq!(self.headers_int.len(), self.headers_float.len());
@@ -440,7 +431,7 @@ impl PrimitiveHeaders {
self.headers_int.push(PrimitiveHeaderI {
z,
- unused: 0,
+ render_task_address,
specific_prim_address: prim_header.specific_prim_address.as_int(),
transform_id: prim_header.transform_id,
user_data,
@@ -480,7 +471,7 @@ pub struct PrimitiveHeaderI {
pub z: ZBufferId,
pub specific_prim_address: i32,
pub transform_id: TransformPaletteId,
- pub unused: i32, // To ensure required 16 byte alignment of vertex textures
+ pub render_task_address: RenderTaskAddress,
pub user_data: [i32; 4],
}
@@ -501,7 +492,6 @@ impl GlyphInstance {
// header since they are constant, and some can be
// compressed to a smaller size.
pub fn build(&self,
- render_task: RenderTaskAddress,
clip_task: RenderTaskAddress,
subpx_dir: SubpixelDirection,
glyph_index_in_text_run: i32,
@@ -511,8 +501,7 @@ impl GlyphInstance {
PrimitiveInstanceData {
data: [
self.prim_header_index.0 as i32,
- ((render_task.0 as i32) << 16)
- | clip_task.0 as i32,
+ clip_task.0 as i32,
(subpx_dir as u32 as i32) << 24
| (color_mode as u32 as i32) << 16
| glyph_index_in_text_run,
@@ -536,7 +525,7 @@ impl From<SplitCompositeInstance> for PrimitiveInstanceData {
instance.prim_header_index.0,
instance.polygons_address,
instance.z.0,
- instance.render_task_address.0 as i32,
+ instance.render_task_address.0,
],
}
}
@@ -547,7 +536,8 @@ impl From<SplitCompositeInstance> for PrimitiveInstanceData {
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct QuadInstance {
pub render_task_address: RenderTaskAddress,
- pub prim_address: GpuBufferAddress,
+ pub prim_address_i: GpuBufferAddress,
+ pub prim_address_f: GpuBufferAddress,
pub z_id: ZBufferId,
pub transform_id: TransformPaletteId,
pub quad_flags: u8,
@@ -559,19 +549,23 @@ pub struct QuadInstance {
impl From<QuadInstance> for PrimitiveInstanceData {
fn from(instance: QuadInstance) -> Self {
/*
- [32 bits prim address]
- [8 bits quad flags] [8 bits edge flags] [16 bits render task address]
- [8 bits segment flags] [24 bits z_id]
- [8 bits segment index] [24 bits xf_id]
- */
+ [32 prim address_i]
+ [32 prim address_f]
+ [8888 qf ef pi si]
+ [32 render task address]
+ */
+
PrimitiveInstanceData {
data: [
- instance.prim_address.as_int(),
- ((instance.quad_flags as i32) << 24) |
- ((instance.edge_flags as i32) << 16) |
- instance.render_task_address.0 as i32,
- ((instance.part_index as i32) << 24) | instance.z_id.0,
- ((instance.segment_index as i32) << 24) | instance.transform_id.0 as i32,
+ instance.prim_address_i.as_int(),
+ instance.prim_address_f.as_int(),
+
+ ((instance.quad_flags as i32) << 24) |
+ ((instance.edge_flags as i32) << 16) |
+ ((instance.part_index as i32) << 8) |
+ ((instance.segment_index as i32) << 0),
+
+ instance.render_task_address.0,
],
}
}
@@ -659,7 +653,6 @@ impl core::fmt::Debug for BrushFlags {
/// Convenience structure to encode into PrimitiveInstanceData.
pub struct BrushInstance {
pub prim_header_index: PrimitiveHeaderIndex,
- pub render_task_address: RenderTaskAddress,
pub clip_task_address: RenderTaskAddress,
pub segment_index: i32,
pub edge_flags: EdgeAaSegmentMask,
@@ -672,8 +665,7 @@ impl From<BrushInstance> for PrimitiveInstanceData {
PrimitiveInstanceData {
data: [
instance.prim_header_index.0,
- ((instance.render_task_address.0 as i32) << 16)
- | instance.clip_task_address.0 as i32,
+ instance.clip_task_address.0,
instance.segment_index
| ((instance.brush_flags.bits() as i32) << 16)
| ((instance.edge_flags.bits() as i32) << 28),
diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs
index e8746ad161..1f1fd5e4f6 100644
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -139,11 +139,11 @@ use std::collections::hash_map::Entry;
use std::ops::Range;
use crate::picture_textures::PictureCacheTextureHandle;
use crate::util::{MaxRect, VecHelper, MatrixHelpers, Recycler, ScaleOffset};
-use crate::filterdata::{FilterDataHandle};
+use crate::filterdata::FilterDataHandle;
use crate::tile_cache::{SliceDebugInfo, TileDebugInfo, DirtyTileDebugInfo};
use crate::visibility::{PrimitiveVisibilityFlags, FrameVisibilityContext};
use crate::visibility::{VisibilityState, FrameVisibilityState};
-use crate::scene_building::{SliceFlags};
+use crate::scene_building::SliceFlags;
// Maximum blur radius for blur filter (different than box-shadow blur).
// Taken from FilterNodeSoftware.cpp in Gecko.
@@ -3951,7 +3951,7 @@ impl SurfaceInfo {
&self,
local_rect: &PictureRect,
spatial_tree: &SpatialTree,
- ) -> Option<DeviceRect> {
+ ) -> Option<DeviceIntRect> {
let local_rect = match local_rect.intersection(&self.clipping_rect) {
Some(rect) => rect,
None => return None,
@@ -3969,10 +3969,21 @@ impl SurfaceInfo {
local_to_world.map(&local_rect).unwrap()
} else {
+ // The content should have been culled out earlier.
+ assert!(self.device_pixel_scale.0 > 0.0);
+
local_rect.cast_unit()
};
- Some((raster_rect * self.device_pixel_scale).round_out())
+ let surface_rect = (raster_rect * self.device_pixel_scale).round_out().to_i32();
+ if surface_rect.is_empty() {
+ // The local_rect computed above may have non-empty size that is very
+ // close to zero. Due to limited arithmetic precision, the SpaceMapper
+ // might transform the near-zero-sized rect into a zero-sized one.
+ return None;
+ }
+
+ Some(surface_rect)
}
}
@@ -5014,7 +5025,7 @@ impl PicturePrimitive {
let content_device_rect = content_device_rect
.intersection(&max_content_rect)
- .expect("bug: no intersection with tile dirty rect");
+ .expect("bug: no intersection with tile dirty rect: {content_device_rect:?} / {max_content_rect:?}");
let content_task_size = content_device_rect.size();
let normalized_content_rect = content_task_size.into();
@@ -6128,22 +6139,28 @@ impl PicturePrimitive {
PictureCompositeMode::TileCache { slice_id } => {
let tile_cache = tile_caches.get_mut(&slice_id).unwrap();
- // We only update the raster scale if we're in high quality zoom mode, or there is no
- // pinch-zoom active. This means that in low quality pinch-zoom, we retain the initial
- // scale factor until the zoom ends, then select a high quality zoom factor for the next
- // frame to be drawn.
- let update_raster_scale =
- !frame_context.fb_config.low_quality_pinch_zoom ||
- !frame_context.spatial_tree.get_spatial_node(tile_cache.spatial_node_index).is_ancestor_or_self_zooming;
-
- if update_raster_scale {
- // Get the complete scale-offset from local space to device space
- let local_to_device = get_relative_scale_offset(
- tile_cache.spatial_node_index,
- frame_context.root_spatial_node_index,
- frame_context.spatial_tree,
- );
+ // Get the complete scale-offset from local space to device space
+ let local_to_device = get_relative_scale_offset(
+ tile_cache.spatial_node_index,
+ frame_context.root_spatial_node_index,
+ frame_context.spatial_tree,
+ );
+ let local_to_cur_raster_scale = local_to_device.scale.x / tile_cache.current_raster_scale;
+ // We only update the raster scale if we're in high quality zoom mode, or there is no
+ // pinch-zoom active, or the zoom has doubled or halved since the raster scale was
+ // last updated. During a low-quality zoom we therefore typically retain the previous
+ // scale factor, which avoids expensive re-rasterizations, except for when the zoom
+ // has become too large or too small when we re-rasterize to avoid bluriness or a
+ // proliferation of picture cache tiles. When the zoom ends we select a high quality
+ // scale factor for the next frame to be drawn.
+ if !frame_context.fb_config.low_quality_pinch_zoom
+ || !frame_context
+ .spatial_tree.get_spatial_node(tile_cache.spatial_node_index)
+ .is_ancestor_or_self_zooming
+ || local_to_cur_raster_scale <= 0.5
+ || local_to_cur_raster_scale >= 2.0
+ {
tile_cache.current_raster_scale = local_to_device.scale.x;
}
diff --git a/gfx/wr/webrender/src/prepare.rs b/gfx/wr/webrender/src/prepare.rs
index f32c94073e..a59eca0670 100644
--- a/gfx/wr/webrender/src/prepare.rs
+++ b/gfx/wr/webrender/src/prepare.rs
@@ -28,18 +28,18 @@ use crate::prim_store::line_dec::MAX_LINE_DECORATION_RESOLUTION;
use crate::prim_store::*;
use crate::prim_store::gradient::GradientGpuBlockBuilder;
use crate::render_backend::DataStores;
-use crate::render_task_graph::{RenderTaskId};
+use crate::render_task_graph::RenderTaskId;
use crate::render_task_cache::RenderTaskCacheKeyKind;
use crate::render_task_cache::{RenderTaskCacheKey, to_cache_size, RenderTaskParent};
use crate::render_task::{RenderTaskKind, RenderTask, SubPass, MaskSubPass, EmptyTask};
-use crate::renderer::{GpuBufferBuilder, GpuBufferAddress};
+use crate::renderer::{GpuBufferBuilderF, GpuBufferAddress};
use crate::segment::{EdgeAaSegmentMask, SegmentBuilder};
use crate::space::SpaceMapper;
use crate::util::{clamp_to_scale_factor, pack_as_float, MaxRect};
use crate::visibility::{compute_conservative_visible_rect, PrimitiveVisibility, VisibilityState};
-const MAX_MASK_SIZE: f32 = 4096.0;
+const MAX_MASK_SIZE: i32 = 4096;
const MIN_BRUSH_SPLIT_SIZE: f32 = 256.0;
const MIN_BRUSH_SPLIT_AREA: f32 = 128.0 * 128.0;
@@ -141,14 +141,32 @@ fn can_use_clip_chain_for_quad_path(
true
}
+/// Describes how clipping affects the rendering of a quad primitive.
+///
+/// As a general rule, parts of the quad that require masking are prerendered in an
+/// intermediate target and the mask is applied using multiplicative blending to
+/// the intermediate result before compositing it into the destination target.
+///
+/// Each segment can opt in or out of masking independently.
#[derive(Debug, Copy, Clone)]
pub enum QuadRenderStrategy {
+ /// The quad is not affected by any mask and is drawn directly in the destination
+ /// target.
Direct,
+ /// The quad is drawn entirely in an intermediate target and a mask is applied
+ /// before compositing in the destination target.
Indirect,
+ /// A rounded rectangle clip is applied to the quad primitive via a nine-patch.
+ /// The segments of the nine-patch that require a mask are rendered and masked in
+ /// an intermediate target, while other segments are drawn directly in the destination
+ /// target.
NinePatch {
radius: LayoutVector2D,
clip_rect: LayoutRect,
},
+ /// Split the primitive into coarse tiles so that each tile independently
+ /// has the opportunity to be drawn directly in the destination target or
+ /// via an intermediate target if it is affected by a mask.
Tiled {
x_tiles: u16,
y_tiles: u16,
@@ -163,69 +181,67 @@ fn get_prim_render_strategy(
can_use_nine_patch: bool,
spatial_tree: &SpatialTree,
) -> QuadRenderStrategy {
- if clip_chain.needs_mask {
- fn tile_count_for_size(size: f32) -> u16 {
- (size / MIN_BRUSH_SPLIT_SIZE).min(4.0).max(1.0).ceil() as u16
- }
+ if !clip_chain.needs_mask {
+ return QuadRenderStrategy::Direct
+ }
- let prim_coverage_size = clip_chain.pic_coverage_rect.size();
- let x_tiles = tile_count_for_size(prim_coverage_size.width);
- let y_tiles = tile_count_for_size(prim_coverage_size.height);
- let try_split_prim = x_tiles > 1 || y_tiles > 1;
-
- if try_split_prim {
- if can_use_nine_patch {
- if clip_chain.clips_range.count == 1 {
- let clip_instance = clip_store.get_instance_from_range(&clip_chain.clips_range, 0);
- let clip_node = &data_stores.clip[clip_instance.handle];
-
- if let ClipItemKind::RoundedRectangle { ref radius, mode: ClipMode::Clip, rect, .. } = clip_node.item.kind {
- let max_corner_width = radius.top_left.width
- .max(radius.bottom_left.width)
- .max(radius.top_right.width)
- .max(radius.bottom_right.width);
- let max_corner_height = radius.top_left.height
- .max(radius.bottom_left.height)
- .max(radius.top_right.height)
- .max(radius.bottom_right.height);
-
- if max_corner_width <= 0.5 * rect.size().width &&
- max_corner_height <= 0.5 * rect.size().height {
-
- let clip_prim_coords_match = spatial_tree.is_matching_coord_system(
- prim_spatial_node_index,
- clip_node.item.spatial_node_index,
- );
+ fn tile_count_for_size(size: f32) -> u16 {
+ (size / MIN_BRUSH_SPLIT_SIZE).min(4.0).max(1.0).ceil() as u16
+ }
- if clip_prim_coords_match {
- let map_clip_to_prim = SpaceMapper::new_with_target(
- prim_spatial_node_index,
- clip_node.item.spatial_node_index,
- LayoutRect::max_rect(),
- spatial_tree,
- );
+ let prim_coverage_size = clip_chain.pic_coverage_rect.size();
+ let x_tiles = tile_count_for_size(prim_coverage_size.width);
+ let y_tiles = tile_count_for_size(prim_coverage_size.height);
+ let try_split_prim = x_tiles > 1 || y_tiles > 1;
- if let Some(rect) = map_clip_to_prim.map(&rect) {
- return QuadRenderStrategy::NinePatch {
- radius: LayoutVector2D::new(max_corner_width, max_corner_height),
- clip_rect: rect,
- };
- }
- }
- }
+ if !try_split_prim {
+ return QuadRenderStrategy::Indirect;
+ }
+
+ if can_use_nine_patch && clip_chain.clips_range.count == 1 {
+ let clip_instance = clip_store.get_instance_from_range(&clip_chain.clips_range, 0);
+ let clip_node = &data_stores.clip[clip_instance.handle];
+
+ if let ClipItemKind::RoundedRectangle { ref radius, mode: ClipMode::Clip, rect, .. } = clip_node.item.kind {
+ let max_corner_width = radius.top_left.width
+ .max(radius.bottom_left.width)
+ .max(radius.top_right.width)
+ .max(radius.bottom_right.width);
+ let max_corner_height = radius.top_left.height
+ .max(radius.bottom_left.height)
+ .max(radius.top_right.height)
+ .max(radius.bottom_right.height);
+
+ if max_corner_width <= 0.5 * rect.size().width &&
+ max_corner_height <= 0.5 * rect.size().height {
+
+ let clip_prim_coords_match = spatial_tree.is_matching_coord_system(
+ prim_spatial_node_index,
+ clip_node.item.spatial_node_index,
+ );
+
+ if clip_prim_coords_match {
+ let map_clip_to_prim = SpaceMapper::new_with_target(
+ prim_spatial_node_index,
+ clip_node.item.spatial_node_index,
+ LayoutRect::max_rect(),
+ spatial_tree,
+ );
+
+ if let Some(rect) = map_clip_to_prim.map(&rect) {
+ return QuadRenderStrategy::NinePatch {
+ radius: LayoutVector2D::new(max_corner_width, max_corner_height),
+ clip_rect: rect,
+ };
}
}
}
-
- QuadRenderStrategy::Tiled {
- x_tiles,
- y_tiles,
- }
- } else {
- QuadRenderStrategy::Indirect
}
- } else {
- QuadRenderStrategy::Direct
+ }
+
+ QuadRenderStrategy::Tiled {
+ x_tiles,
+ y_tiles,
}
}
@@ -452,7 +468,7 @@ fn prepare_interned_prim_for_render(
kind: RenderTaskCacheKeyKind::LineDecoration(cache_key.clone()),
},
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,
@@ -607,7 +623,7 @@ fn prepare_interned_prim_for_render(
handles.push(frame_state.resource_cache.request_render_task(
cache_key,
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false, // TODO(gw): We don't calculate opacity for borders yet!
@@ -764,7 +780,7 @@ fn prepare_interned_prim_for_render(
// the written block count) to gpu-buffer, we could add a trait for
// writing typed data?
let main_prim_address = write_prim_blocks(
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
prim_data.common.prim_rect,
prim_instance.vis.clip_chain.local_clip_rect,
premul_color,
@@ -787,24 +803,21 @@ fn prepare_interned_prim_for_render(
}
QuadRenderStrategy::Indirect => {
let surface = &frame_state.surfaces[pic_context.surface_index.0];
- let clipped_surface_rect = surface.get_surface_rect(
+ let Some(clipped_surface_rect) = surface.get_surface_rect(
&prim_instance.vis.clip_chain.pic_coverage_rect,
frame_context.spatial_tree,
- ).expect("bug: what can cause this?");
-
- let p0 = clipped_surface_rect.min.floor();
- let p1 = clipped_surface_rect.max.ceil();
+ ) else {
+ return;
+ };
- let x0 = p0.x;
- let y0 = p0.y;
- let x1 = p1.x;
- let y1 = p1.y;
+ let p0 = clipped_surface_rect.min.to_f32();
+ let p1 = clipped_surface_rect.max.to_f32();
let segment = add_segment(
- x0,
- y0,
- x1,
- y1,
+ p0.x,
+ p0.y,
+ p1.x,
+ p1.y,
true,
prim_instance,
prim_spatial_node_index,
@@ -820,7 +833,7 @@ fn prepare_interned_prim_for_render(
add_composite_prim(
prim_instance_index,
- LayoutRect::new(LayoutPoint::new(x0, y0), LayoutPoint::new(x1, y1)),
+ LayoutRect::new(p0.cast_unit(), p1.cast_unit()),
premul_color,
quad_flags,
frame_state,
@@ -831,10 +844,12 @@ fn prepare_interned_prim_for_render(
QuadRenderStrategy::Tiled { x_tiles, y_tiles } => {
let surface = &frame_state.surfaces[pic_context.surface_index.0];
- let clipped_surface_rect = surface.get_surface_rect(
+ let Some(clipped_surface_rect) = surface.get_surface_rect(
&prim_instance.vis.clip_chain.pic_coverage_rect,
frame_context.spatial_tree,
- ).expect("bug: what can cause this?");
+ ) else {
+ return;
+ };
let unclipped_surface_rect = surface.map_to_device_rect(
&prim_instance.vis.clip_chain.pic_coverage_rect,
@@ -843,21 +858,21 @@ fn prepare_interned_prim_for_render(
scratch.quad_segments.clear();
- let mut x_coords = vec![clipped_surface_rect.min.x.round()];
- let mut y_coords = vec![clipped_surface_rect.min.y.round()];
+ let mut x_coords = vec![clipped_surface_rect.min.x];
+ let mut y_coords = vec![clipped_surface_rect.min.y];
- let dx = (clipped_surface_rect.max.x - clipped_surface_rect.min.x) / x_tiles as f32;
- let dy = (clipped_surface_rect.max.y - clipped_surface_rect.min.y) / y_tiles as f32;
+ let dx = (clipped_surface_rect.max.x - clipped_surface_rect.min.x) as f32 / x_tiles as f32;
+ let dy = (clipped_surface_rect.max.y - clipped_surface_rect.min.y) as f32 / y_tiles as f32;
- for x in 1 .. x_tiles {
- x_coords.push((clipped_surface_rect.min.x + x as f32 * dx).round());
+ for x in 1 .. (x_tiles as i32) {
+ x_coords.push((clipped_surface_rect.min.x as f32 + x as f32 * dx).round() as i32);
}
- for y in 1 .. y_tiles {
- y_coords.push((clipped_surface_rect.min.y + y as f32 * dy).round());
+ for y in 1 .. (y_tiles as i32) {
+ y_coords.push((clipped_surface_rect.min.y as f32 + y as f32 * dy).round() as i32);
}
- x_coords.push(clipped_surface_rect.max.x.round());
- y_coords.push(clipped_surface_rect.max.y.round());
+ x_coords.push(clipped_surface_rect.max.x);
+ y_coords.push(clipped_surface_rect.max.y);
for y in 0 .. y_coords.len()-1 {
let y0 = y_coords[y];
@@ -877,18 +892,11 @@ fn prepare_interned_prim_for_render(
let create_task = true;
- let r = DeviceRect::new(DevicePoint::new(x0, y0), DevicePoint::new(x1, y1));
-
- let x0 = r.min.x;
- let y0 = r.min.y;
- let x1 = r.max.x;
- let y1 = r.max.y;
-
let segment = add_segment(
- x0,
- y0,
- x1,
- y1,
+ x0 as f32,
+ y0 as f32,
+ x1 as f32,
+ y1 as f32,
create_task,
prim_instance,
prim_spatial_node_index,
@@ -917,10 +925,12 @@ fn prepare_interned_prim_for_render(
}
QuadRenderStrategy::NinePatch { clip_rect, radius } => {
let surface = &frame_state.surfaces[pic_context.surface_index.0];
- let clipped_surface_rect = surface.get_surface_rect(
+ let Some(clipped_surface_rect) = surface.get_surface_rect(
&prim_instance.vis.clip_chain.pic_coverage_rect,
frame_context.spatial_tree,
- ).expect("bug: what can cause this?");
+ ) else {
+ return;
+ };
let unclipped_surface_rect = surface.map_to_device_rect(
&prim_instance.vis.clip_chain.pic_coverage_rect,
@@ -943,17 +953,17 @@ fn prepare_interned_prim_for_render(
let surface_rect_0 = surface.map_to_device_rect(
&pic_corner_0,
frame_context.spatial_tree,
- );
+ ).round_out().to_i32();
let surface_rect_1 = surface.map_to_device_rect(
&pic_corner_1,
frame_context.spatial_tree,
- );
+ ).round_out().to_i32();
- let p0 = surface_rect_0.min.floor();
- let p1 = surface_rect_0.max.ceil();
- let p2 = surface_rect_1.min.floor();
- let p3 = surface_rect_1.max.ceil();
+ let p0 = surface_rect_0.min;
+ let p1 = surface_rect_0.max;
+ let p2 = surface_rect_1.min;
+ let p3 = surface_rect_1.max;
let mut x_coords = [p0.x, p1.x, p2.x, p3.x];
let mut y_coords = [p0.y, p1.y, p2.y, p3.y];
@@ -985,7 +995,10 @@ fn prepare_interned_prim_for_render(
true
};
- let r = DeviceRect::new(DevicePoint::new(x0, y0), DevicePoint::new(x1, y1));
+ let r = DeviceIntRect::new(
+ DeviceIntPoint::new(x0, y0),
+ DeviceIntPoint::new(x1, y1),
+ );
let r = match r.intersection(&clipped_surface_rect) {
Some(r) => r,
@@ -994,16 +1007,11 @@ fn prepare_interned_prim_for_render(
}
};
- let x0 = r.min.x;
- let y0 = r.min.y;
- let x1 = r.max.x;
- let y1 = r.max.y;
-
let segment = add_segment(
- x0,
- y0,
- x1,
- y1,
+ r.min.x as f32,
+ r.min.y as f32,
+ r.max.x as f32,
+ r.max.y as f32,
create_task,
prim_instance,
prim_spatial_node_index,
@@ -1138,7 +1146,7 @@ fn prepare_interned_prim_for_render(
let stops_address = GradientGpuBlockBuilder::build(
prim_data.reverse_stops,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
&prim_data.stops,
);
@@ -1296,8 +1304,8 @@ fn prepare_interned_prim_for_render(
.clipped_local_rect
.cast_unit();
- let main_prim_address = write_prim_blocks(
- frame_state.frame_gpu_data,
+ let prim_address_f = write_prim_blocks(
+ &mut frame_state.frame_gpu_data.f32,
prim_local_rect,
prim_instance.vis.clip_chain.local_clip_rect,
PremultipliedColorF::WHITE,
@@ -1333,7 +1341,7 @@ fn prepare_interned_prim_for_render(
let masks = MaskSubPass {
clip_node_range,
prim_spatial_node_index,
- main_prim_address,
+ prim_address_f,
};
// Add the mask as a sub-pass of the picture
@@ -1353,30 +1361,22 @@ fn prepare_interned_prim_for_render(
let device_pixel_scale = surface.device_pixel_scale;
let raster_spatial_node_index = surface.raster_spatial_node_index;
- let clipped_surface_rect = surface.get_surface_rect(
+ let Some(clipped_surface_rect) = surface.get_surface_rect(
&coverage_rect,
frame_context.spatial_tree,
- ).expect("bug: what can cause this?");
-
- let p0 = clipped_surface_rect.min.floor();
- let x0 = p0.x;
- let y0 = p0.y;
-
- let content_origin = DevicePoint::new(x0, y0);
+ ) else {
+ return;
+ };
// Draw a normal screens-space mask to an alpha target that
// can be sampled when compositing this picture.
let empty_task = EmptyTask {
- content_origin,
+ content_origin: clipped_surface_rect.min.to_f32(),
device_pixel_scale,
raster_spatial_node_index,
};
- let p1 = clipped_surface_rect.max.ceil();
- let x1 = p1.x;
- let y1 = p1.y;
-
- let task_size = DeviceSize::new(x1 - x0, y1 - y0).round().to_i32();
+ let task_size = clipped_surface_rect.size();
let clip_task_id = frame_state.rg_builder.add().init(RenderTask::new_dynamic(
task_size,
@@ -1406,7 +1406,7 @@ fn prepare_interned_prim_for_render(
let masks = MaskSubPass {
clip_node_range,
prim_spatial_node_index,
- main_prim_address,
+ prim_address_f,
};
let clip_task = frame_state.rg_builder.get_task_mut(clip_task_id);
@@ -1814,13 +1814,19 @@ pub fn update_clip_task(
unadjusted_device_rect,
device_pixel_scale,
);
+
+ if device_rect.size().to_i32().is_empty() {
+ log::warn!("Bad adjusted clip task size {:?} (was {:?})", device_rect.size(), unadjusted_device_rect.size());
+ return false;
+ }
+
let clip_task_id = RenderTaskKind::new_mask(
device_rect,
instance.vis.clip_chain.clips_range,
root_spatial_node_index,
frame_state.clip_store,
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.resource_cache,
frame_state.rg_builder,
&mut data_stores.clip,
@@ -1865,7 +1871,7 @@ pub fn update_brush_segment_clip_task(
return ClipMaskKind::None;
}
- let device_rect = match frame_state.surfaces[surface_index.0].get_surface_rect(
+ let unadjusted_device_rect = match frame_state.surfaces[surface_index.0].get_surface_rect(
&clip_chain.pic_coverage_rect,
frame_context.spatial_tree,
) {
@@ -1873,7 +1879,12 @@ pub fn update_brush_segment_clip_task(
None => return ClipMaskKind::Clipped,
};
- let (device_rect, device_pixel_scale) = adjust_mask_scale_for_max_size(device_rect, device_pixel_scale);
+ let (device_rect, device_pixel_scale) = adjust_mask_scale_for_max_size(unadjusted_device_rect, device_pixel_scale);
+
+ if device_rect.size().to_i32().is_empty() {
+ log::warn!("Bad adjusted mask size {:?} (was {:?})", device_rect.size(), unadjusted_device_rect.size());
+ return ClipMaskKind::Clipped;
+ }
let clip_task_id = RenderTaskKind::new_mask(
device_rect,
@@ -1881,7 +1892,7 @@ pub fn update_brush_segment_clip_task(
root_spatial_node_index,
frame_state.clip_store,
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.resource_cache,
frame_state.rg_builder,
clip_data_store,
@@ -2101,15 +2112,17 @@ fn build_segments_if_needed(
}
// Ensures that the size of mask render tasks are within MAX_MASK_SIZE.
-fn adjust_mask_scale_for_max_size(device_rect: DeviceRect, device_pixel_scale: DevicePixelScale) -> (DeviceRect, DevicePixelScale) {
+fn adjust_mask_scale_for_max_size(device_rect: DeviceIntRect, device_pixel_scale: DevicePixelScale) -> (DeviceIntRect, DevicePixelScale) {
if device_rect.width() > MAX_MASK_SIZE || device_rect.height() > MAX_MASK_SIZE {
// round_out will grow by 1 integer pixel if origin is on a
// fractional position, so keep that margin for error with -1:
- let scale = (MAX_MASK_SIZE - 1.0) /
- f32::max(device_rect.width(), device_rect.height());
+ let device_rect_f = device_rect.to_f32();
+ let scale = (MAX_MASK_SIZE - 1) as f32 /
+ f32::max(device_rect_f.width(), device_rect_f.height());
let new_device_pixel_scale = device_pixel_scale * Scale::new(scale);
- let new_device_rect = (device_rect.to_f32() * Scale::new(scale))
- .round_out();
+ let new_device_rect = (device_rect_f * Scale::new(scale))
+ .round_out()
+ .to_i32();
(new_device_rect, new_device_pixel_scale)
} else {
(device_rect, device_pixel_scale)
@@ -2117,7 +2130,7 @@ fn adjust_mask_scale_for_max_size(device_rect: DeviceRect, device_pixel_scale: D
}
pub fn write_prim_blocks(
- builder: &mut GpuBufferBuilder,
+ builder: &mut GpuBufferBuilderF,
prim_rect: LayoutRect,
clip_rect: LayoutRect,
color: PremultipliedColorF,
@@ -2153,7 +2166,7 @@ fn add_segment(
prim_instance: &PrimitiveInstance,
prim_spatial_node_index: SpatialNodeIndex,
raster_spatial_node_index: SpatialNodeIndex,
- main_prim_address: GpuBufferAddress,
+ prim_address_f: GpuBufferAddress,
transform_id: TransformPaletteId,
aa_flags: EdgeAaSegmentMask,
quad_flags: QuadFlags,
@@ -2177,7 +2190,7 @@ fn add_segment(
raster_spatial_node_index,
device_pixel_scale,
content_origin,
- main_prim_address,
+ prim_address_f,
transform_id,
aa_flags,
quad_flags,
@@ -2189,7 +2202,7 @@ fn add_segment(
let masks = MaskSubPass {
clip_node_range: prim_instance.vis.clip_chain.clips_range,
prim_spatial_node_index,
- main_prim_address,
+ prim_address_f,
};
let task = frame_state.rg_builder.get_task_mut(task_id);
@@ -2223,7 +2236,7 @@ fn add_composite_prim(
segments: &[QuadSegment],
) {
let composite_prim_address = write_prim_blocks(
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
rect,
rect,
color,
diff --git a/gfx/wr/webrender/src/prim_store/gradient/conic.rs b/gfx/wr/webrender/src/prim_store/gradient/conic.rs
index d9c3f5d350..2c4818095e 100644
--- a/gfx/wr/webrender/src/prim_store/gradient/conic.rs
+++ b/gfx/wr/webrender/src/prim_store/gradient/conic.rs
@@ -254,7 +254,7 @@ impl ConicGradientTemplate {
kind: RenderTaskCacheKeyKind::ConicGradient(cache_key),
},
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,
diff --git a/gfx/wr/webrender/src/prim_store/gradient/linear.rs b/gfx/wr/webrender/src/prim_store/gradient/linear.rs
index 85da4b670a..7075daac0d 100644
--- a/gfx/wr/webrender/src/prim_store/gradient/linear.rs
+++ b/gfx/wr/webrender/src/prim_store/gradient/linear.rs
@@ -522,7 +522,7 @@ impl LinearGradientTemplate {
kind: RenderTaskCacheKeyKind::FastLinearGradient(gradient),
},
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,
@@ -552,7 +552,7 @@ impl LinearGradientTemplate {
kind: RenderTaskCacheKeyKind::LinearGradient(cache_key),
},
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,
diff --git a/gfx/wr/webrender/src/prim_store/gradient/mod.rs b/gfx/wr/webrender/src/prim_store/gradient/mod.rs
index d0b922c579..a0410549b0 100644
--- a/gfx/wr/webrender/src/prim_store/gradient/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/gradient/mod.rs
@@ -4,7 +4,7 @@
use api::{ColorF, ColorU, GradientStop, PremultipliedColorF};
use api::units::{LayoutRect, LayoutSize, LayoutVector2D};
-use crate::renderer::{GpuBufferAddress, GpuBufferBuilder};
+use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF};
use std::hash;
mod linear;
@@ -167,7 +167,7 @@ impl GradientGpuBlockBuilder {
// Build the gradient data from the supplied stops, reversing them if necessary.
pub fn build(
reverse_stops: bool,
- gpu_buffer_builder: &mut GpuBufferBuilder,
+ gpu_buffer_builder: &mut GpuBufferBuilderF,
src_stops: &[GradientStop],
) -> GpuBufferAddress {
// Preconditions (should be ensured by DisplayListBuilder):
diff --git a/gfx/wr/webrender/src/prim_store/gradient/radial.rs b/gfx/wr/webrender/src/prim_store/gradient/radial.rs
index f3f20f9a55..4d91b28633 100644
--- a/gfx/wr/webrender/src/prim_store/gradient/radial.rs
+++ b/gfx/wr/webrender/src/prim_store/gradient/radial.rs
@@ -220,7 +220,7 @@ impl RadialGradientTemplate {
kind: RenderTaskCacheKeyKind::RadialGradient(cache_key),
},
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,
diff --git a/gfx/wr/webrender/src/prim_store/image.rs b/gfx/wr/webrender/src/prim_store/image.rs
index 6007b4ba9a..8a05965536 100644
--- a/gfx/wr/webrender/src/prim_store/image.rs
+++ b/gfx/wr/webrender/src/prim_store/image.rs
@@ -257,7 +257,7 @@ impl ImageData {
kind: RenderTaskCacheKeyKind::Image(image_cache_key),
},
frame_state.gpu_cache,
- frame_state.frame_gpu_data,
+ &mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
descriptor.is_opaque(),
diff --git a/gfx/wr/webrender/src/prim_store/mod.rs b/gfx/wr/webrender/src/prim_store/mod.rs
index db5480f597..cc09eab6b1 100644
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -1312,6 +1312,37 @@ impl PrimitiveScratchBuffer {
}
}
+ pub fn push_debug_rect_with_stroke_width(
+ &mut self,
+ rect: WorldRect,
+ border: ColorF,
+ stroke_width: f32
+ ) {
+ let top_edge = WorldRect::new(
+ WorldPoint::new(rect.min.x + stroke_width, rect.min.y),
+ WorldPoint::new(rect.max.x - stroke_width, rect.min.y + stroke_width)
+ );
+ self.push_debug_rect(top_edge * DevicePixelScale::new(1.0), border, border);
+
+ let bottom_edge = WorldRect::new(
+ WorldPoint::new(rect.min.x + stroke_width, rect.max.y - stroke_width),
+ WorldPoint::new(rect.max.x - stroke_width, rect.max.y)
+ );
+ self.push_debug_rect(bottom_edge * DevicePixelScale::new(1.0), border, border);
+
+ let right_edge = WorldRect::new(
+ WorldPoint::new(rect.max.x - stroke_width, rect.min.y),
+ rect.max
+ );
+ self.push_debug_rect(right_edge * DevicePixelScale::new(1.0), border, border);
+
+ let left_edge = WorldRect::new(
+ rect.min,
+ WorldPoint::new(rect.min.x + stroke_width, rect.max.y)
+ );
+ self.push_debug_rect(left_edge * DevicePixelScale::new(1.0), border, border);
+ }
+
#[allow(dead_code)]
pub fn push_debug_rect(
&mut self,
diff --git a/gfx/wr/webrender/src/render_target.rs b/gfx/wr/webrender/src/render_target.rs
index 0db77d5ce0..f2d1c24c10 100644
--- a/gfx/wr/webrender/src/render_target.rs
+++ b/gfx/wr/webrender/src/render_target.rs
@@ -24,7 +24,7 @@ use crate::prim_store::gradient::{
FastLinearGradientInstance, LinearGradientInstance, RadialGradientInstance,
ConicGradientInstance,
};
-use crate::renderer::{GpuBufferBuilder, GpuBufferAddress};
+use crate::renderer::{GpuBufferAddress, GpuBufferBuilder};
use crate::render_backend::DataStores;
use crate::render_task::{RenderTaskKind, RenderTaskAddress, SubPass};
use crate::render_task::{RenderTask, ScalingTask, SvgFilterInfo, MaskSubPass};
@@ -104,6 +104,7 @@ pub trait RenderTarget {
_z_generator: &mut ZBufferIdGenerator,
_prim_instances: &[PrimitiveInstance],
_cmd_buffers: &CommandBufferList,
+ _gpu_buffer_builder: &mut GpuBufferBuilder,
) {
}
@@ -183,6 +184,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
z_generator: &mut ZBufferIdGenerator,
prim_instances: &[PrimitiveInstance],
cmd_buffers: &CommandBufferList,
+ gpu_buffer_builder: &mut GpuBufferBuilder,
) {
if self.targets.is_empty() {
return;
@@ -198,6 +200,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
z_generator,
prim_instances,
cmd_buffers,
+ gpu_buffer_builder,
);
}
}
@@ -274,10 +277,10 @@ impl RenderTarget for ColorRenderTarget {
z_generator: &mut ZBufferIdGenerator,
prim_instances: &[PrimitiveInstance],
cmd_buffers: &CommandBufferList,
+ gpu_buffer_builder: &mut GpuBufferBuilder,
) {
profile_scope!("build");
let mut merged_batches = AlphaBatchContainer::new(None);
- let mut gpu_buffer_builder = GpuBufferBuilder::new();
for task_id in &self.alpha_tasks {
profile_scope!("alpha_task");
@@ -326,7 +329,7 @@ impl RenderTarget for ColorRenderTarget {
pic_task.surface_spatial_node_index,
z_generator,
prim_instances,
- &mut gpu_buffer_builder,
+ gpu_buffer_builder,
segments,
);
});
@@ -376,13 +379,14 @@ impl RenderTarget for ColorRenderTarget {
add_quad_to_batch(
render_task_address,
info.transform_id,
- info.prim_address,
+ info.prim_address_f,
info.quad_flags,
info.edge_flags,
INVALID_SEGMENT_INDEX as u8,
RenderTaskId::INVALID,
ZBufferId(0),
render_tasks,
+ gpu_buffer_builder,
|_, instance| {
if info.prim_needs_scissor_rect {
self.prim_instances_with_scissor
@@ -921,6 +925,7 @@ fn add_svg_filter_instances(
kind,
input_count,
generic_int,
+ padding: 0,
extra_data_address: extra_data_address.unwrap_or(GpuCacheAddress::INVALID),
};
@@ -978,7 +983,7 @@ fn build_mask_tasks(
let (clip_address, fast_path) = match clip_node.item.kind {
ClipItemKind::RoundedRectangle { rect, radius, mode } => {
let (fast_path, clip_address) = if radius.is_uniform().is_some() {
- let mut writer = gpu_buffer_builder.write_blocks(3);
+ let mut writer = gpu_buffer_builder.f32.write_blocks(3);
writer.push_one(rect);
writer.push_one([radius.top_left.width, 0.0, 0.0, 0.0]);
writer.push_one([mode as i32 as f32, 0.0, 0.0, 0.0]);
@@ -986,7 +991,7 @@ fn build_mask_tasks(
(true, clip_address)
} else {
- let mut writer = gpu_buffer_builder.write_blocks(4);
+ let mut writer = gpu_buffer_builder.f32.write_blocks(4);
writer.push_one(rect);
writer.push_one([
radius.top_left.width,
@@ -1011,7 +1016,7 @@ fn build_mask_tasks(
ClipItemKind::Rectangle { rect, mode, .. } => {
assert_eq!(mode, ClipMode::Clip);
- let mut writer = gpu_buffer_builder.write_blocks(3);
+ let mut writer = gpu_buffer_builder.f32.write_blocks(3);
writer.push_one(rect);
writer.push_one([0.0, 0.0, 0.0, 0.0]);
writer.push_one([mode as i32 as f32, 0.0, 0.0, 0.0]);
@@ -1043,7 +1048,7 @@ fn build_mask_tasks(
for tile in clip_store.visible_mask_tiles(&clip_instance) {
let clip_prim_address = write_prim_blocks(
- gpu_buffer_builder,
+ &mut gpu_buffer_builder.f32,
rect,
rect,
PremultipliedColorF::WHITE,
@@ -1067,6 +1072,7 @@ fn build_mask_tasks(
tile.task_id,
ZBufferId(0),
render_tasks,
+ gpu_buffer_builder,
|_, prim| {
if clip_needs_scissor_rect {
results
@@ -1107,7 +1113,7 @@ fn build_mask_tasks(
);
let main_prim_address = write_prim_blocks(
- gpu_buffer_builder,
+ &mut gpu_buffer_builder.f32,
task_world_rect.cast_unit(),
task_world_rect.cast_unit(),
PremultipliedColorF::WHITE,
@@ -1162,6 +1168,7 @@ fn build_mask_tasks(
RenderTaskId::INVALID,
ZBufferId(0),
render_tasks,
+ gpu_buffer_builder,
|_, prim| {
let instance = MaskInstance {
prim,
@@ -1235,7 +1242,7 @@ fn build_sub_pass(
render_task_address,
content_rect / device_pixel_scale,
target_rect,
- masks.main_prim_address,
+ masks.prim_address_f,
masks.prim_spatial_node_index,
raster_spatial_node_index,
ctx.clip_store,
diff --git a/gfx/wr/webrender/src/render_task.rs b/gfx/wr/webrender/src/render_task.rs
index 4e920cb356..8889ae1ea6 100644
--- a/gfx/wr/webrender/src/render_task.rs
+++ b/gfx/wr/webrender/src/render_task.rs
@@ -10,7 +10,7 @@ use crate::clip::{ClipDataStore, ClipItemKind, ClipStore, ClipNodeRange};
use crate::command_buffer::{CommandBufferIndex, QuadFlags};
use crate::spatial_tree::SpatialNodeIndex;
use crate::filterdata::SFilterData;
-use crate::frame_builder::{FrameBuilderConfig};
+use crate::frame_builder::FrameBuilderConfig;
use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
use crate::gpu_types::{BorderInstance, ImageSource, UvRectKind, TransformPaletteId};
use crate::internal_types::{CacheTextureId, FastHashMap, TextureSource, Swizzle};
@@ -22,7 +22,7 @@ use crate::prim_store::gradient::{
};
use crate::resource_cache::{ResourceCache, ImageRequest};
use std::{usize, f32, i32, u32};
-use crate::renderer::{GpuBufferAddress, GpuBufferBuilder};
+use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF};
use crate::render_target::{ResolveOp, RenderTargetKind};
use crate::render_task_graph::{PassId, RenderTaskId, RenderTaskGraphBuilder};
use crate::render_task_cache::{RenderTaskCacheEntryHandle, RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskParent};
@@ -46,11 +46,11 @@ fn render_task_sanity_check(size: &DeviceIntSize) {
#[repr(C)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
-pub struct RenderTaskAddress(pub u16);
+pub struct RenderTaskAddress(pub i32);
impl Into<RenderTaskAddress> for RenderTaskId {
fn into(self) -> RenderTaskAddress {
- RenderTaskAddress(self.index as u16)
+ RenderTaskAddress(self.index as i32)
}
}
@@ -186,7 +186,7 @@ pub struct EmptyTask {
pub struct PrimTask {
pub device_pixel_scale: DevicePixelScale,
pub content_origin: DevicePoint,
- pub prim_address: GpuBufferAddress,
+ pub prim_address_f: GpuBufferAddress,
pub prim_spatial_node_index: SpatialNodeIndex,
pub raster_spatial_node_index: SpatialNodeIndex,
pub transform_id: TransformPaletteId,
@@ -520,7 +520,7 @@ impl RenderTaskKind {
raster_spatial_node_index: SpatialNodeIndex,
device_pixel_scale: DevicePixelScale,
content_origin: DevicePoint,
- prim_address: GpuBufferAddress,
+ prim_address_f: GpuBufferAddress,
transform_id: TransformPaletteId,
edge_flags: EdgeAaSegmentMask,
quad_flags: QuadFlags,
@@ -532,7 +532,7 @@ impl RenderTaskKind {
raster_spatial_node_index,
device_pixel_scale,
content_origin,
- prim_address,
+ prim_address_f,
transform_id,
edge_flags,
quad_flags,
@@ -588,12 +588,12 @@ impl RenderTaskKind {
}
pub fn new_mask(
- outer_rect: DeviceRect,
+ outer_rect: DeviceIntRect,
clip_node_range: ClipNodeRange,
root_spatial_node_index: SpatialNodeIndex,
clip_store: &mut ClipStore,
gpu_cache: &mut GpuCache,
- gpu_buffer_builder: &mut GpuBufferBuilder,
+ gpu_buffer_builder: &mut GpuBufferBuilderF,
resource_cache: &mut ResourceCache,
rg_builder: &mut RenderTaskGraphBuilder,
clip_data_store: &mut ClipDataStore,
@@ -610,7 +610,7 @@ impl RenderTaskKind {
// TODO(gw): If this ever shows up in a profile, we could pre-calculate
// whether a ClipSources contains any box-shadows and skip
// this iteration for the majority of cases.
- let task_size = outer_rect.size().to_i32();
+ let task_size = outer_rect.size();
// If we have a potentially tiled clip mask, clear the mask area first. Otherwise,
// the first (primary) clip mask will overwrite all the clip mask pixels with
@@ -620,7 +620,7 @@ impl RenderTaskKind {
RenderTask::new_dynamic(
task_size,
RenderTaskKind::CacheMask(CacheMaskTask {
- actual_rect: outer_rect,
+ actual_rect: outer_rect.to_f32(),
clip_node_range,
root_spatial_node_index,
device_pixel_scale,
@@ -883,7 +883,7 @@ pub type TaskDependencies = SmallVec<[RenderTaskId;2]>;
pub struct MaskSubPass {
pub clip_node_range: ClipNodeRange,
pub prim_spatial_node_index: SpatialNodeIndex,
- pub main_prim_address: GpuBufferAddress,
+ pub prim_address_f: GpuBufferAddress,
}
#[cfg_attr(feature = "capture", derive(Serialize))]
@@ -940,6 +940,9 @@ impl RenderTask {
size: DeviceIntSize,
kind: RenderTaskKind,
) -> Self {
+ if size.is_empty() {
+ log::warn!("Bad {} render task size: {:?}", kind.as_str(), size);
+ }
RenderTask::new(
RenderTaskLocation::Unallocated { size },
kind,
diff --git a/gfx/wr/webrender/src/render_task_cache.rs b/gfx/wr/webrender/src/render_task_cache.rs
index 0454c1214f..2c81a9824f 100644
--- a/gfx/wr/webrender/src/render_task_cache.rs
+++ b/gfx/wr/webrender/src/render_task_cache.rs
@@ -22,7 +22,7 @@ use crate::resource_cache::CacheItem;
use std::{mem, usize, f32, i32};
use crate::surface::SurfaceBuilder;
use crate::texture_cache::{TextureCache, TextureCacheHandle, Eviction, TargetShader};
-use crate::renderer::GpuBufferBuilder;
+use crate::renderer::GpuBufferBuilderF;
use crate::render_target::RenderTargetKind;
use crate::render_task::{RenderTask, StaticRenderTaskSurface, RenderTaskLocation, RenderTaskKind, CachedTask};
use crate::render_task_graph::{RenderTaskGraphBuilder, RenderTaskId};
@@ -228,7 +228,7 @@ impl RenderTaskCache {
key: RenderTaskCacheKey,
texture_cache: &mut TextureCache,
gpu_cache: &mut GpuCache,
- gpu_buffer_builder: &mut GpuBufferBuilder,
+ gpu_buffer_builder: &mut GpuBufferBuilderF,
rg_builder: &mut RenderTaskGraphBuilder,
user_data: Option<[f32; 4]>,
is_opaque: bool,
@@ -237,7 +237,7 @@ impl RenderTaskCache {
f: F,
) -> Result<RenderTaskId, ()>
where
- F: FnOnce(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilder) -> Result<RenderTaskId, ()>,
+ F: FnOnce(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF) -> Result<RenderTaskId, ()>,
{
let frame_id = self.frame_id;
let size = key.size;
diff --git a/gfx/wr/webrender/src/render_task_graph.rs b/gfx/wr/webrender/src/render_task_graph.rs
index 29ecf66a2e..6c02de8b65 100644
--- a/gfx/wr/webrender/src/render_task_graph.rs
+++ b/gfx/wr/webrender/src/render_task_graph.rs
@@ -445,6 +445,13 @@ impl RenderTaskGraphBuilder {
)
};
+ if surface_size.is_empty() {
+ // We would panic in the guillotine allocator. Instead, panic here
+ // with some context.
+ let task_name = graph.tasks[task_id.index as usize].kind.as_str();
+ panic!("{} render task has invalid size {:?}", task_name, surface_size);
+ }
+
let format = match kind {
RenderTargetKind::Color => ImageFormat::RGBA8,
RenderTargetKind::Alpha => ImageFormat::R8,
diff --git a/gfx/wr/webrender/src/renderer/gpu_buffer.rs b/gfx/wr/webrender/src/renderer/gpu_buffer.rs
index 58a8aa6cbd..c8a2b87b0c 100644
--- a/gfx/wr/webrender/src/renderer/gpu_buffer.rs
+++ b/gfx/wr/webrender/src/renderer/gpu_buffer.rs
@@ -13,21 +13,57 @@
use crate::renderer::MAX_VERTEX_TEXTURE_WIDTH;
use api::units::{DeviceIntRect, DeviceIntSize, LayoutRect, PictureRect, DeviceRect};
-use api::{PremultipliedColorF};
+use api::{PremultipliedColorF, ImageFormat};
use crate::device::Texel;
use crate::render_task_graph::{RenderTaskGraph, RenderTaskId};
+pub struct GpuBufferBuilder {
+ pub i32: GpuBufferBuilderI,
+ pub f32: GpuBufferBuilderF,
+}
+
+pub type GpuBufferF = GpuBuffer<GpuBufferBlockF>;
+pub type GpuBufferBuilderF = GpuBufferBuilderImpl<GpuBufferBlockF>;
+
+pub type GpuBufferI = GpuBuffer<GpuBufferBlockI>;
+pub type GpuBufferBuilderI = GpuBufferBuilderImpl<GpuBufferBlockI>;
+
+unsafe impl Texel for GpuBufferBlockF {
+ fn image_format() -> ImageFormat { ImageFormat::RGBAF32 }
+}
+
+unsafe impl Texel for GpuBufferBlockI {
+ fn image_format() -> ImageFormat { ImageFormat::RGBAI32 }
+}
-unsafe impl Texel for GpuBufferBlock {}
+impl Default for GpuBufferBlockF {
+ fn default() -> Self {
+ GpuBufferBlockF::EMPTY
+ }
+}
+
+impl Default for GpuBufferBlockI {
+ fn default() -> Self {
+ GpuBufferBlockI::EMPTY
+ }
+}
/// A single texel in RGBAF32 texture - 16 bytes.
#[derive(Copy, Clone, Debug, MallocSizeOf)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
-pub struct GpuBufferBlock {
+pub struct GpuBufferBlockF {
data: [f32; 4],
}
+/// A single texel in RGBAI32 texture - 16 bytes.
+#[derive(Copy, Clone, Debug, MallocSizeOf)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub struct GpuBufferBlockI {
+ data: [i32; 4],
+}
+
#[derive(Copy, Debug, Clone, MallocSizeOf, Eq, PartialEq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
@@ -48,13 +84,17 @@ impl GpuBufferAddress {
pub const INVALID: GpuBufferAddress = GpuBufferAddress { u: !0, v: !0 };
}
-impl GpuBufferBlock {
- pub const EMPTY: Self = GpuBufferBlock { data: [0.0; 4] };
+impl GpuBufferBlockF {
+ pub const EMPTY: Self = GpuBufferBlockF { data: [0.0; 4] };
+}
+
+impl GpuBufferBlockI {
+ pub const EMPTY: Self = GpuBufferBlockI { data: [0; 4] };
}
-impl Into<GpuBufferBlock> for LayoutRect {
- fn into(self) -> GpuBufferBlock {
- GpuBufferBlock {
+impl Into<GpuBufferBlockF> for LayoutRect {
+ fn into(self) -> GpuBufferBlockF {
+ GpuBufferBlockF {
data: [
self.min.x,
self.min.y,
@@ -65,9 +105,9 @@ impl Into<GpuBufferBlock> for LayoutRect {
}
}
-impl Into<GpuBufferBlock> for PictureRect {
- fn into(self) -> GpuBufferBlock {
- GpuBufferBlock {
+impl Into<GpuBufferBlockF> for PictureRect {
+ fn into(self) -> GpuBufferBlockF {
+ GpuBufferBlockF {
data: [
self.min.x,
self.min.y,
@@ -78,9 +118,9 @@ impl Into<GpuBufferBlock> for PictureRect {
}
}
-impl Into<GpuBufferBlock> for DeviceRect {
- fn into(self) -> GpuBufferBlock {
- GpuBufferBlock {
+impl Into<GpuBufferBlockF> for DeviceRect {
+ fn into(self) -> GpuBufferBlockF {
+ GpuBufferBlockF {
data: [
self.min.x,
self.min.y,
@@ -91,9 +131,9 @@ impl Into<GpuBufferBlock> for DeviceRect {
}
}
-impl Into<GpuBufferBlock> for PremultipliedColorF {
- fn into(self) -> GpuBufferBlock {
- GpuBufferBlock {
+impl Into<GpuBufferBlockF> for PremultipliedColorF {
+ fn into(self) -> GpuBufferBlockF {
+ GpuBufferBlockF {
data: [
self.r,
self.g,
@@ -104,22 +144,43 @@ impl Into<GpuBufferBlock> for PremultipliedColorF {
}
}
-impl Into<GpuBufferBlock> for DeviceIntRect {
- fn into(self) -> GpuBufferBlock {
- GpuBufferBlock {
+impl From<DeviceIntRect> for GpuBufferBlockF {
+ fn from(rect: DeviceIntRect) -> Self {
+ GpuBufferBlockF {
+ data: [
+ rect.min.x as f32,
+ rect.min.y as f32,
+ rect.max.x as f32,
+ rect.max.y as f32,
+ ],
+ }
+ }
+}
+
+impl From<DeviceIntRect> for GpuBufferBlockI {
+ fn from(rect: DeviceIntRect) -> Self {
+ GpuBufferBlockI {
data: [
- self.min.x as f32,
- self.min.y as f32,
- self.max.x as f32,
- self.max.y as f32,
+ rect.min.x,
+ rect.min.y,
+ rect.max.x,
+ rect.max.y,
],
}
}
}
-impl Into<GpuBufferBlock> for [f32; 4] {
- fn into(self) -> GpuBufferBlock {
- GpuBufferBlock {
+impl Into<GpuBufferBlockF> for [f32; 4] {
+ fn into(self) -> GpuBufferBlockF {
+ GpuBufferBlockF {
+ data: self,
+ }
+ }
+}
+
+impl Into<GpuBufferBlockI> for [i32; 4] {
+ fn into(self) -> GpuBufferBlockI {
+ GpuBufferBlockI {
data: self,
}
}
@@ -132,16 +193,16 @@ struct DeferredBlock {
}
/// Interface to allow writing multiple GPU blocks, possibly of different types
-pub struct GpuBufferWriter<'a> {
- buffer: &'a mut Vec<GpuBufferBlock>,
+pub struct GpuBufferWriter<'a, T> {
+ buffer: &'a mut Vec<T>,
deferred: &'a mut Vec<DeferredBlock>,
index: usize,
block_count: usize,
}
-impl<'a> GpuBufferWriter<'a> {
+impl<'a, T> GpuBufferWriter<'a, T> where T: Texel {
fn new(
- buffer: &'a mut Vec<GpuBufferBlock>,
+ buffer: &'a mut Vec<T>,
deferred: &'a mut Vec<DeferredBlock>,
index: usize,
block_count: usize,
@@ -155,7 +216,7 @@ impl<'a> GpuBufferWriter<'a> {
}
/// Push one (16 byte) block of data in to the writer
- pub fn push_one<B>(&mut self, block: B) where B: Into<GpuBufferBlock> {
+ pub fn push_one<B>(&mut self, block: B) where B: Into<T> {
self.buffer.push(block.into());
}
@@ -166,7 +227,7 @@ impl<'a> GpuBufferWriter<'a> {
task_id,
index: self.buffer.len(),
});
- self.buffer.push(GpuBufferBlock::EMPTY);
+ self.buffer.push(T::default());
}
/// Close this writer, returning the GPU address of this set of block(s).
@@ -180,20 +241,20 @@ impl<'a> GpuBufferWriter<'a> {
}
}
-impl<'a> Drop for GpuBufferWriter<'a> {
+impl<'a, T> Drop for GpuBufferWriter<'a, T> {
fn drop(&mut self) {
assert_eq!(self.buffer.len(), self.index + self.block_count, "Claimed block_count was not written");
}
}
-pub struct GpuBufferBuilder {
- data: Vec<GpuBufferBlock>,
+pub struct GpuBufferBuilderImpl<T> {
+ data: Vec<T>,
deferred: Vec<DeferredBlock>,
}
-impl GpuBufferBuilder {
+impl<T> GpuBufferBuilderImpl<T> where T: Texel + std::convert::From<DeviceIntRect> {
pub fn new() -> Self {
- GpuBufferBuilder {
+ GpuBufferBuilderImpl {
data: Vec::new(),
deferred: Vec::new(),
}
@@ -202,13 +263,13 @@ impl GpuBufferBuilder {
#[allow(dead_code)]
pub fn push(
&mut self,
- blocks: &[GpuBufferBlock],
+ blocks: &[T],
) -> GpuBufferAddress {
assert!(blocks.len() <= MAX_VERTEX_TEXTURE_WIDTH);
if (self.data.len() % MAX_VERTEX_TEXTURE_WIDTH) + blocks.len() > MAX_VERTEX_TEXTURE_WIDTH {
while self.data.len() % MAX_VERTEX_TEXTURE_WIDTH != 0 {
- self.data.push(GpuBufferBlock::EMPTY);
+ self.data.push(T::default());
}
}
@@ -226,12 +287,12 @@ impl GpuBufferBuilder {
pub fn write_blocks(
&mut self,
block_count: usize,
- ) -> GpuBufferWriter {
+ ) -> GpuBufferWriter<T> {
assert!(block_count <= MAX_VERTEX_TEXTURE_WIDTH);
if (self.data.len() % MAX_VERTEX_TEXTURE_WIDTH) + block_count > MAX_VERTEX_TEXTURE_WIDTH {
while self.data.len() % MAX_VERTEX_TEXTURE_WIDTH != 0 {
- self.data.push(GpuBufferBlock::EMPTY);
+ self.data.push(T::default());
}
}
@@ -248,11 +309,11 @@ impl GpuBufferBuilder {
pub fn finalize(
mut self,
render_tasks: &RenderTaskGraph,
- ) -> GpuBuffer {
+ ) -> GpuBuffer<T> {
let required_len = (self.data.len() + MAX_VERTEX_TEXTURE_WIDTH-1) & !(MAX_VERTEX_TEXTURE_WIDTH-1);
for _ in 0 .. required_len - self.data.len() {
- self.data.push(GpuBufferBlock::EMPTY);
+ self.data.push(T::default());
}
let len = self.data.len();
@@ -271,18 +332,20 @@ impl GpuBufferBuilder {
GpuBuffer {
data: self.data,
size: DeviceIntSize::new(MAX_VERTEX_TEXTURE_WIDTH as i32, (len / MAX_VERTEX_TEXTURE_WIDTH) as i32),
+ format: T::image_format(),
}
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
-pub struct GpuBuffer {
- pub data: Vec<GpuBufferBlock>,
+pub struct GpuBuffer<T> {
+ pub data: Vec<T>,
pub size: DeviceIntSize,
+ pub format: ImageFormat,
}
-impl GpuBuffer {
+impl<T> GpuBuffer<T> {
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
@@ -292,13 +355,13 @@ impl GpuBuffer {
#[test]
fn test_gpu_buffer_sizing_push() {
let render_task_graph = RenderTaskGraph::new_for_testing();
- let mut builder = GpuBufferBuilder::new();
+ let mut builder = GpuBufferBuilderF::new();
- let row = vec![GpuBufferBlock::EMPTY; MAX_VERTEX_TEXTURE_WIDTH];
+ let row = vec![GpuBufferBlockF::EMPTY; MAX_VERTEX_TEXTURE_WIDTH];
builder.push(&row);
- builder.push(&[GpuBufferBlock::EMPTY]);
- builder.push(&[GpuBufferBlock::EMPTY]);
+ builder.push(&[GpuBufferBlockF::EMPTY]);
+ builder.push(&[GpuBufferBlockF::EMPTY]);
let buffer = builder.finalize(&render_task_graph);
assert_eq!(buffer.data.len(), MAX_VERTEX_TEXTURE_WIDTH * 2);
@@ -307,20 +370,20 @@ fn test_gpu_buffer_sizing_push() {
#[test]
fn test_gpu_buffer_sizing_writer() {
let render_task_graph = RenderTaskGraph::new_for_testing();
- let mut builder = GpuBufferBuilder::new();
+ let mut builder = GpuBufferBuilderF::new();
let mut writer = builder.write_blocks(MAX_VERTEX_TEXTURE_WIDTH);
for _ in 0 .. MAX_VERTEX_TEXTURE_WIDTH {
- writer.push_one(GpuBufferBlock::EMPTY);
+ writer.push_one(GpuBufferBlockF::EMPTY);
}
writer.finish();
let mut writer = builder.write_blocks(1);
- writer.push_one(GpuBufferBlock::EMPTY);
+ writer.push_one(GpuBufferBlockF::EMPTY);
writer.finish();
let mut writer = builder.write_blocks(1);
- writer.push_one(GpuBufferBlock::EMPTY);
+ writer.push_one(GpuBufferBlockF::EMPTY);
writer.finish();
let buffer = builder.finalize(&render_task_graph);
diff --git a/gfx/wr/webrender/src/renderer/mod.rs b/gfx/wr/webrender/src/renderer/mod.rs
index 0eded7ffb4..3a058ae8f4 100644
--- a/gfx/wr/webrender/src/renderer/mod.rs
+++ b/gfx/wr/webrender/src/renderer/mod.rs
@@ -59,7 +59,7 @@ use crate::composite::{CompositorConfig, NativeSurfaceOperationDetails, NativeSu
use crate::composite::{TileKind};
use crate::debug_colors;
use crate::device::{DepthFunction, Device, DrawTarget, ExternalTexture, GpuFrameId, UploadPBOPool};
-use crate::device::{ReadTarget, ShaderError, Texture, TextureFilter, TextureFlags, TextureSlot};
+use crate::device::{ReadTarget, ShaderError, Texture, TextureFilter, TextureFlags, TextureSlot, Texel};
use crate::device::query::{GpuSampler, GpuTimer};
#[cfg(feature = "capture")]
use crate::device::FBOId;
@@ -127,7 +127,7 @@ pub(crate) mod init;
pub use debug::DebugRenderer;
pub use shade::{Shaders, SharedShaders};
pub use vertex::{desc, VertexArrayKind, MAX_VERTEX_TEXTURE_WIDTH};
-pub use gpu_buffer::{GpuBuffer, GpuBufferBuilder, GpuBufferAddress};
+pub use gpu_buffer::{GpuBuffer, GpuBufferF, GpuBufferBuilderF, GpuBufferI, GpuBufferBuilderI, GpuBufferAddress, GpuBufferBuilder};
/// The size of the array of each type of vertex data texture that
/// is round-robin-ed each frame during bind_frame_data. Doing this
@@ -341,7 +341,8 @@ pub(crate) enum TextureSampler {
PrimitiveHeadersF,
PrimitiveHeadersI,
ClipMask,
- GpuBuffer,
+ GpuBufferF,
+ GpuBufferI,
}
impl TextureSampler {
@@ -370,7 +371,8 @@ impl Into<TextureSlot> for TextureSampler {
TextureSampler::PrimitiveHeadersF => TextureSlot(7),
TextureSampler::PrimitiveHeadersI => TextureSlot(8),
TextureSampler::ClipMask => TextureSlot(9),
- TextureSampler::GpuBuffer => TextureSlot(10),
+ TextureSampler::GpuBufferF => TextureSlot(10),
+ TextureSampler::GpuBufferI => TextureSlot(11),
}
}
}
@@ -3616,7 +3618,6 @@ impl Renderer {
fn draw_clip_batch_list(
&mut self,
list: &ClipBatchList,
- draw_target: &DrawTarget,
projection: &default::Transform3D<f32>,
stats: &mut RendererStats,
) {
@@ -3671,42 +3672,6 @@ impl Renderer {
stats,
);
}
-
- // draw image masks
- let mut using_scissor = false;
- for ((mask_texture_id, clip_rect), items) in list.images.iter() {
- let _gm2 = self.gpu_profiler.start_marker("clip images");
- // Some image masks may require scissoring to ensure they don't draw
- // outside their task's target bounds. Axis-aligned primitives will
- // be clamped inside the shader and should not require scissoring.
- // TODO: We currently assume scissor state is off by default for
- // alpha targets here, but in the future we may want to track the
- // current scissor state so that this can be properly saved and
- // restored here.
- if let Some(clip_rect) = clip_rect {
- if !using_scissor {
- self.device.enable_scissor();
- using_scissor = true;
- }
- let scissor_rect = draw_target.build_scissor_rect(Some(*clip_rect));
- self.device.set_scissor_rect(scissor_rect);
- } else if using_scissor {
- self.device.disable_scissor();
- using_scissor = false;
- }
- let textures = BatchTextures::composite_rgb(*mask_texture_id);
- self.shaders.borrow_mut().cs_clip_image
- .bind(&mut self.device, projection, None, &mut self.renderer_errors, &mut self.profile);
- self.draw_instanced_batch(
- items,
- VertexArrayKind::ClipImage,
- &textures,
- stats,
- );
- }
- if using_scissor {
- self.device.disable_scissor();
- }
}
fn draw_alpha_target(
@@ -3861,7 +3826,6 @@ impl Renderer {
self.set_blend(false, FramebufferKind::Other);
self.draw_clip_batch_list(
&target.clip_batcher.primary_clips,
- &draw_target,
projection,
stats,
);
@@ -3872,7 +3836,6 @@ impl Renderer {
self.set_blend_mode_multiply(FramebufferKind::Other);
self.draw_clip_batch_list(
&target.clip_batcher.secondary_clips,
- &draw_target,
projection,
stats,
);
@@ -4452,6 +4415,38 @@ impl Renderer {
}
}
+ fn create_gpu_buffer_texture<T: Texel>(
+ &mut self,
+ buffer: &GpuBuffer<T>,
+ sampler: TextureSampler,
+ ) -> Option<Texture> {
+ if buffer.is_empty() {
+ None
+ } else {
+ let gpu_buffer_texture = self.device.create_texture(
+ ImageBufferKind::Texture2D,
+ buffer.format,
+ buffer.size.width,
+ buffer.size.height,
+ TextureFilter::Nearest,
+ None,
+ );
+
+ self.device.bind_texture(
+ sampler,
+ &gpu_buffer_texture,
+ Swizzle::default(),
+ );
+
+ self.device.upload_texture_immediate(
+ &gpu_buffer_texture,
+ &buffer.data,
+ );
+
+ Some(gpu_buffer_texture)
+ }
+ }
+
fn draw_frame(
&mut self,
frame: &mut Frame,
@@ -4478,31 +4473,14 @@ impl Renderer {
// Upload experimental GPU buffer texture if there is any data present
// TODO: Recycle these textures, upload via PBO or best approach for platform
- let gpu_buffer_texture = if frame.gpu_buffer.is_empty() {
- None
- } else {
- let gpu_buffer_texture = self.device.create_texture(
- ImageBufferKind::Texture2D,
- ImageFormat::RGBAF32,
- frame.gpu_buffer.size.width,
- frame.gpu_buffer.size.height,
- TextureFilter::Nearest,
- None,
- );
-
- self.device.bind_texture(
- TextureSampler::GpuBuffer,
- &gpu_buffer_texture,
- Swizzle::default(),
- );
-
- self.device.upload_texture_immediate(
- &gpu_buffer_texture,
- &frame.gpu_buffer.data,
- );
-
- Some(gpu_buffer_texture)
- };
+ let gpu_buffer_texture_f = self.create_gpu_buffer_texture(
+ &frame.gpu_buffer_f,
+ TextureSampler::GpuBufferF,
+ );
+ let gpu_buffer_texture_i = self.create_gpu_buffer_texture(
+ &frame.gpu_buffer_i,
+ TextureSampler::GpuBufferI,
+ );
// Determine the present mode and dirty rects, if device_size
// is Some(..). If it's None, no composite will occur and only
@@ -4761,8 +4739,11 @@ impl Renderer {
present_mode,
);
- if let Some(gpu_buffer_texture) = gpu_buffer_texture {
- self.device.delete_texture(gpu_buffer_texture);
+ if let Some(gpu_buffer_texture_f) = gpu_buffer_texture_f {
+ self.device.delete_texture(gpu_buffer_texture_f);
+ }
+ if let Some(gpu_buffer_texture_i) = gpu_buffer_texture_i {
+ self.device.delete_texture(gpu_buffer_texture_i);
}
frame.has_been_rendered = true;
diff --git a/gfx/wr/webrender/src/renderer/shade.rs b/gfx/wr/webrender/src/renderer/shade.rs
index 30baee0a19..777bfab44a 100644
--- a/gfx/wr/webrender/src/renderer/shade.rs
+++ b/gfx/wr/webrender/src/renderer/shade.rs
@@ -254,7 +254,6 @@ impl LazilyCompiledShader {
VertexArrayKind::RadialGradient => &desc::RADIAL_GRADIENT,
VertexArrayKind::ConicGradient => &desc::CONIC_GRADIENT,
VertexArrayKind::Blur => &desc::BLUR,
- VertexArrayKind::ClipImage => &desc::CLIP_IMAGE,
VertexArrayKind::ClipRect => &desc::CLIP_RECT,
VertexArrayKind::ClipBoxShadow => &desc::CLIP_BOX_SHADOW,
VertexArrayKind::VectorStencil => &desc::VECTOR_STENCIL,
@@ -282,7 +281,8 @@ impl LazilyCompiledShader {
("sGpuCache", TextureSampler::GpuCache),
("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
- ("sGpuBuffer", TextureSampler::GpuBuffer),
+ ("sGpuBufferF", TextureSampler::GpuBufferF),
+ ("sGpuBufferI", TextureSampler::GpuBufferI),
],
);
}
@@ -300,7 +300,8 @@ impl LazilyCompiledShader {
("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
("sClipMask", TextureSampler::ClipMask),
- ("sGpuBuffer", TextureSampler::GpuBuffer),
+ ("sGpuBufferF", TextureSampler::GpuBufferF),
+ ("sGpuBufferI", TextureSampler::GpuBufferI),
],
);
}
@@ -617,7 +618,6 @@ pub struct Shaders {
pub cs_clip_rectangle_slow: LazilyCompiledShader,
pub cs_clip_rectangle_fast: LazilyCompiledShader,
pub cs_clip_box_shadow: LazilyCompiledShader,
- pub cs_clip_image: LazilyCompiledShader,
// The are "primitive shaders". These shaders draw and blend
// final results on screen. They are aware of tile boundaries.
@@ -817,16 +817,6 @@ impl Shaders {
profile,
)?;
- let cs_clip_image = LazilyCompiledShader::new(
- ShaderKind::ClipCache(VertexArrayKind::ClipImage),
- "cs_clip_image",
- &["TEXTURE_2D"],
- device,
- options.precache_flags,
- &shader_list,
- profile,
- )?;
-
let mut cs_scale = Vec::new();
let scale_shader_num = IMAGE_BUFFER_KINDS.len();
// PrimitiveShader is not clonable. Use push() to initialize the vec.
@@ -1128,7 +1118,6 @@ impl Shaders {
cs_clip_rectangle_slow,
cs_clip_rectangle_fast,
cs_clip_box_shadow,
- cs_clip_image,
ps_text_run,
ps_text_run_dual_source,
ps_quad_textured,
@@ -1274,7 +1263,6 @@ impl Shaders {
self.cs_clip_rectangle_slow.deinit(device);
self.cs_clip_rectangle_fast.deinit(device);
self.cs_clip_box_shadow.deinit(device);
- self.cs_clip_image.deinit(device);
self.ps_text_run.deinit(device);
if let Some(shader) = self.ps_text_run_dual_source {
shader.deinit(device);
diff --git a/gfx/wr/webrender/src/renderer/upload.rs b/gfx/wr/webrender/src/renderer/upload.rs
index 0ba053cd76..c987038651 100644
--- a/gfx/wr/webrender/src/renderer/upload.rs
+++ b/gfx/wr/webrender/src/renderer/upload.rs
@@ -43,6 +43,7 @@ use crate::profiler;
use crate::render_api::MemoryReport;
pub const BATCH_UPLOAD_TEXTURE_SIZE: DeviceIntSize = DeviceIntSize::new(512, 512);
+const BATCH_UPLOAD_FORMAT_COUNT: usize = 4;
/// Upload a number of items to texture cache textures.
///
@@ -627,10 +628,10 @@ pub struct UploadTexturePool {
/// The textures in the pool associated with a last used frame index.
///
/// The outer array corresponds to each of teh three supported texture formats.
- textures: [VecDeque<(Texture, u64)>; 3],
+ textures: [VecDeque<(Texture, u64)>; BATCH_UPLOAD_FORMAT_COUNT],
// Frame at which to deallocate some textures if there are too many in the pool,
// for each format.
- delay_texture_deallocation: [u64; 3],
+ delay_texture_deallocation: [u64; BATCH_UPLOAD_FORMAT_COUNT],
current_frame: u64,
/// Temporary buffers that are used when using staging uploads + glTexImage2D.
@@ -646,8 +647,8 @@ pub struct UploadTexturePool {
impl UploadTexturePool {
pub fn new() -> Self {
UploadTexturePool {
- textures: [VecDeque::new(), VecDeque::new(), VecDeque::new()],
- delay_texture_deallocation: [0; 3],
+ textures: [VecDeque::new(), VecDeque::new(), VecDeque::new(), VecDeque::new()],
+ delay_texture_deallocation: [0; BATCH_UPLOAD_FORMAT_COUNT],
current_frame: 0,
temporary_buffers: Vec::new(),
min_temporary_buffers: 0,
@@ -660,7 +661,8 @@ impl UploadTexturePool {
ImageFormat::RGBA8 => 0,
ImageFormat::BGRA8 => 1,
ImageFormat::R8 => 2,
- _ => { panic!("unexpected format"); }
+ ImageFormat::R16 => 3,
+ _ => { panic!("unexpected format {:?}", format); }
}
}
diff --git a/gfx/wr/webrender/src/renderer/vertex.rs b/gfx/wr/webrender/src/renderer/vertex.rs
index ff555363d8..cd73975ddd 100644
--- a/gfx/wr/webrender/src/renderer/vertex.rs
+++ b/gfx/wr/webrender/src/renderer/vertex.rs
@@ -49,12 +49,12 @@ pub mod desc {
VertexAttribute {
name: "aBlurRenderTaskAddress",
count: 1,
- kind: VertexAttributeKind::U16,
+ kind: VertexAttributeKind::I32,
},
VertexAttribute {
name: "aBlurSourceTaskAddress",
count: 1,
- kind: VertexAttributeKind::U16,
+ kind: VertexAttributeKind::I32,
},
VertexAttribute {
name: "aBlurDirection",
@@ -488,53 +488,6 @@ pub mod desc {
],
};
- pub const CLIP_IMAGE: VertexDescriptor = VertexDescriptor {
- vertex_attributes: &[VertexAttribute {
- name: "aPosition",
- count: 2,
- kind: VertexAttributeKind::U8Norm,
- }],
- instance_attributes: &[
- // common clip attributes
- VertexAttribute {
- name: "aClipDeviceArea",
- count: 4,
- kind: VertexAttributeKind::F32,
- },
- VertexAttribute {
- name: "aClipOrigins",
- count: 4,
- kind: VertexAttributeKind::F32,
- },
- VertexAttribute {
- name: "aDevicePixelScale",
- count: 1,
- kind: VertexAttributeKind::F32,
- },
- VertexAttribute {
- name: "aTransformIds",
- count: 2,
- kind: VertexAttributeKind::I32,
- },
- // specific clip attributes
- VertexAttribute {
- name: "aClipTileRect",
- count: 4,
- kind: VertexAttributeKind::F32,
- },
- VertexAttribute {
- name: "aClipDataResourceAddress",
- count: 2,
- kind: VertexAttributeKind::U16,
- },
- VertexAttribute {
- name: "aClipLocalRect",
- count: 4,
- kind: VertexAttributeKind::F32,
- },
- ],
- };
-
pub const GPU_CACHE_UPDATE: VertexDescriptor = VertexDescriptor {
vertex_attributes: &[
VertexAttribute {
@@ -574,17 +527,17 @@ pub mod desc {
VertexAttribute {
name: "aFilterRenderTaskAddress",
count: 1,
- kind: VertexAttributeKind::U16,
+ kind: VertexAttributeKind::I32,
},
VertexAttribute {
name: "aFilterInput1TaskAddress",
count: 1,
- kind: VertexAttributeKind::U16,
+ kind: VertexAttributeKind::I32,
},
VertexAttribute {
name: "aFilterInput2TaskAddress",
count: 1,
- kind: VertexAttributeKind::U16,
+ kind: VertexAttributeKind::I32,
},
VertexAttribute {
name: "aFilterKind",
@@ -602,6 +555,11 @@ pub mod desc {
kind: VertexAttributeKind::U16,
},
VertexAttribute {
+ name: "aUnused",
+ count: 1,
+ kind: VertexAttributeKind::U16,
+ },
+ VertexAttribute {
name: "aFilterExtraDataAddress",
count: 2,
kind: VertexAttributeKind::U16,
@@ -809,7 +767,6 @@ pub mod desc {
pub enum VertexArrayKind {
Primitive,
Blur,
- ClipImage,
ClipRect,
ClipBoxShadow,
VectorStencil,
@@ -1038,7 +995,6 @@ pub struct RendererVAOs {
blur_vao: VAO,
clip_rect_vao: VAO,
clip_box_shadow_vao: VAO,
- clip_image_vao: VAO,
border_vao: VAO,
line_vao: VAO,
scale_vao: VAO,
@@ -1086,7 +1042,6 @@ impl RendererVAOs {
clip_rect_vao: device.create_vao_with_new_instances(&desc::CLIP_RECT, &prim_vao),
clip_box_shadow_vao: device
.create_vao_with_new_instances(&desc::CLIP_BOX_SHADOW, &prim_vao),
- clip_image_vao: device.create_vao_with_new_instances(&desc::CLIP_IMAGE, &prim_vao),
border_vao: device.create_vao_with_new_instances(&desc::BORDER, &prim_vao),
scale_vao: device.create_vao_with_new_instances(&desc::SCALE, &prim_vao),
line_vao: device.create_vao_with_new_instances(&desc::LINE, &prim_vao),
@@ -1109,7 +1064,6 @@ impl RendererVAOs {
device.delete_vao(self.resolve_vao);
device.delete_vao(self.clip_rect_vao);
device.delete_vao(self.clip_box_shadow_vao);
- device.delete_vao(self.clip_image_vao);
device.delete_vao(self.fast_linear_gradient_vao);
device.delete_vao(self.linear_gradient_vao);
device.delete_vao(self.radial_gradient_vao);
@@ -1131,7 +1085,6 @@ impl ops::Index<VertexArrayKind> for RendererVAOs {
fn index(&self, kind: VertexArrayKind) -> &VAO {
match kind {
VertexArrayKind::Primitive => &self.prim_vao,
- VertexArrayKind::ClipImage => &self.clip_image_vao,
VertexArrayKind::ClipRect => &self.clip_rect_vao,
VertexArrayKind::ClipBoxShadow => &self.clip_box_shadow_vao,
VertexArrayKind::Blur => &self.blur_vao,
diff --git a/gfx/wr/webrender/src/resource_cache.rs b/gfx/wr/webrender/src/resource_cache.rs
index 9459bf86da..349be25cb8 100644
--- a/gfx/wr/webrender/src/resource_cache.rs
+++ b/gfx/wr/webrender/src/resource_cache.rs
@@ -34,7 +34,7 @@ use crate::profiler::{self, TransactionProfile, bytes_to_mb};
use crate::render_task_graph::{RenderTaskId, RenderTaskGraphBuilder};
use crate::render_task_cache::{RenderTaskCache, RenderTaskCacheKey, RenderTaskParent};
use crate::render_task_cache::{RenderTaskCacheEntry, RenderTaskCacheEntryHandle};
-use crate::renderer::GpuBufferBuilder;
+use crate::renderer::GpuBufferBuilderF;
use crate::surface::SurfaceBuilder;
use euclid::point2;
use smallvec::SmallVec;
@@ -594,7 +594,7 @@ impl ResourceCache {
&mut self,
key: RenderTaskCacheKey,
gpu_cache: &mut GpuCache,
- gpu_buffer_builder: &mut GpuBufferBuilder,
+ gpu_buffer_builder: &mut GpuBufferBuilderF,
rg_builder: &mut RenderTaskGraphBuilder,
user_data: Option<[f32; 4]>,
is_opaque: bool,
@@ -603,7 +603,7 @@ impl ResourceCache {
f: F,
) -> RenderTaskId
where
- F: FnOnce(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilder) -> RenderTaskId,
+ F: FnOnce(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF) -> RenderTaskId,
{
self.cached_render_tasks.request_render_task(
key,
@@ -2087,14 +2087,14 @@ impl ResourceCache {
index,
}
}
- #[cfg(not(target_os = "macos"))]
+ #[cfg(not(any(target_os = "macos", target_os = "ios")))]
FontTemplate::Native(native) => {
PlainFontTemplate {
data: native.path.to_string_lossy().to_string(),
index: native.index,
}
}
- #[cfg(target_os = "macos")]
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
FontTemplate::Native(native) => {
PlainFontTemplate {
data: native.name,
diff --git a/gfx/wr/webrender/src/spatial_node.rs b/gfx/wr/webrender/src/spatial_node.rs
index 9a2039e37b..6bf1313e0d 100644
--- a/gfx/wr/webrender/src/spatial_node.rs
+++ b/gfx/wr/webrender/src/spatial_node.rs
@@ -673,7 +673,7 @@ impl SpatialNode {
pub fn prepare_state_for_children(&self, state: &mut TransformUpdateState) {
state.current_coordinate_system_id = self.coordinate_system_id;
- state.is_ancestor_or_self_zooming = self.is_async_zooming;
+ state.is_ancestor_or_self_zooming = self.is_ancestor_or_self_zooming;
state.invertible &= self.invertible;
// The transformation we are passing is the transformation of the parent
diff --git a/gfx/wr/webrender/src/spatial_tree.rs b/gfx/wr/webrender/src/spatial_tree.rs
index c2cd422076..0aa6bb5296 100644
--- a/gfx/wr/webrender/src/spatial_tree.rs
+++ b/gfx/wr/webrender/src/spatial_tree.rs
@@ -2042,3 +2042,46 @@ fn test_world_transforms() {
st.get_world_viewport_transform(scroll).into_transform(),
LayoutToWorldTransform::identity());
}
+
+/// Tests that a spatial node that is async zooming and all of its descendants
+/// are correctly marked as having themselves an ancestor that is zooming.
+#[test]
+fn test_is_ancestor_or_self_zooming() {
+ let mut cst = SceneSpatialTree::new();
+ let root_reference_frame_index = cst.root_reference_frame_index();
+
+ let root = add_reference_frame(
+ &mut cst,
+ root_reference_frame_index,
+ LayoutTransform::identity(),
+ LayoutVector2D::zero(),
+ SpatialTreeItemKey::new(0, 0),
+ );
+ let child1 = add_reference_frame(
+ &mut cst,
+ root,
+ LayoutTransform::identity(),
+ LayoutVector2D::zero(),
+ SpatialTreeItemKey::new(0, 1),
+ );
+ let child2 = add_reference_frame(
+ &mut cst,
+ child1,
+ LayoutTransform::identity(),
+ LayoutVector2D::zero(),
+ SpatialTreeItemKey::new(0, 2),
+ );
+
+ let mut st = SpatialTree::new();
+ st.apply_updates(cst.end_frame_and_get_pending_updates());
+
+ // Mark the root node as async zooming
+ st.get_spatial_node_mut(root).is_async_zooming = true;
+ st.update_tree(&SceneProperties::new());
+
+ // Ensure that the root node and all descendants are marked as having
+ // themselves or an ancestor zooming
+ assert!(st.get_spatial_node(root).is_ancestor_or_self_zooming);
+ assert!(st.get_spatial_node(child1).is_ancestor_or_self_zooming);
+ assert!(st.get_spatial_node(child2).is_ancestor_or_self_zooming);
+}
diff --git a/gfx/wr/webrender/src/telemetry.rs b/gfx/wr/webrender/src/telemetry.rs
index 9b4c02d68e..5fd67bb80c 100644
--- a/gfx/wr/webrender/src/telemetry.rs
+++ b/gfx/wr/webrender/src/telemetry.rs
@@ -2,6 +2,7 @@
* 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/. */
+#[cfg(feature = "gecko")]
use glean::TimerId;
#[cfg(feature = "gecko")]
use firefox_on_glean::metrics::wr;
@@ -9,16 +10,19 @@ use std::time::Duration;
pub struct Telemetry;
+#[cfg(not(feature = "gecko"))]
+pub struct TimerId;
+
/// Defines the interface for hooking up an external telemetry reporter to WR.
#[cfg(not(feature = "gecko"))]
impl Telemetry {
pub fn record_rasterize_blobs_time(_duration: Duration) { }
- pub fn start_framebuild_time() -> TimerId { TimerId { id: 0 } }
+ pub fn start_framebuild_time() -> TimerId { TimerId }
pub fn stop_and_accumulate_framebuild_time(_id: TimerId) { }
pub fn record_renderer_time(_duration: Duration) { }
pub fn record_renderer_time_no_sc(_duration: Duration) { }
pub fn record_scenebuild_time(_duration: Duration) { }
- pub fn start_sceneswap_time() -> TimerId { TimerId { id: 0 } }
+ pub fn start_sceneswap_time() -> TimerId { TimerId }
pub fn stop_and_accumulate_sceneswap_time(_id: TimerId) { }
pub fn cancel_sceneswap_time(_id: TimerId) { }
pub fn record_texture_cache_update_time(_duration: Duration) { }
diff --git a/gfx/wr/webrender_api/src/font.rs b/gfx/wr/webrender_api/src/font.rs
index d4f3057a7c..fc245ddfab 100644
--- a/gfx/wr/webrender_api/src/font.rs
+++ b/gfx/wr/webrender_api/src/font.rs
@@ -5,7 +5,7 @@
use peek_poke::PeekPoke;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
-#[cfg(not(target_os = "macos"))]
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
use std::path::PathBuf;
use std::sync::Arc;
// local imports
@@ -52,14 +52,14 @@ impl FontSize {
pub fn to_f64_px(&self) -> f64 { self.0 as f64 }
}
-#[cfg(not(target_os = "macos"))]
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct NativeFontHandle {
pub path: PathBuf,
pub index: u32,
}
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct NativeFontHandle {
pub name: String,
@@ -236,13 +236,13 @@ impl Default for FontInstanceFlags {
FontInstanceFlags::SUBPIXEL_POSITION
}
- #[cfg(target_os = "macos")]
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
fn default() -> FontInstanceFlags {
FontInstanceFlags::SUBPIXEL_POSITION |
FontInstanceFlags::FONT_SMOOTHING
}
- #[cfg(not(any(target_os = "macos", target_os = "windows")))]
+ #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
fn default() -> FontInstanceFlags {
FontInstanceFlags::SUBPIXEL_POSITION
}
@@ -332,14 +332,14 @@ impl Default for FontInstancePlatformOptions {
}
}
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
pub struct FontInstancePlatformOptions {
pub unused: u32,
}
-#[cfg(target_os = "macos")]
+#[cfg(any(target_os = "macos", target_os = "ios"))]
impl Default for FontInstancePlatformOptions {
fn default() -> FontInstancePlatformOptions {
FontInstancePlatformOptions {
@@ -348,7 +348,7 @@ impl Default for FontInstancePlatformOptions {
}
}
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
pub enum FontLCDFilter {
@@ -358,7 +358,7 @@ pub enum FontLCDFilter {
Legacy,
}
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
pub enum FontHinting {
@@ -369,7 +369,7 @@ pub enum FontHinting {
LCD,
}
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
pub struct FontInstancePlatformOptions {
@@ -377,7 +377,7 @@ pub struct FontInstancePlatformOptions {
pub hinting: FontHinting,
}
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
impl Default for FontInstancePlatformOptions {
fn default() -> FontInstancePlatformOptions {
FontInstancePlatformOptions {
diff --git a/gfx/wr/webrender_build/src/shader_features.rs b/gfx/wr/webrender_build/src/shader_features.rs
index 2c5d03dc92..780a24a1aa 100644
--- a/gfx/wr/webrender_build/src/shader_features.rs
+++ b/gfx/wr/webrender_build/src/shader_features.rs
@@ -66,7 +66,6 @@ pub fn get_shader_features(flags: ShaderFeatureFlags) -> ShaderFeatures {
// Clip shaders
shaders.insert("cs_clip_rectangle", vec![String::new(), "FAST_PATH".to_string()]);
- shaders.insert("cs_clip_image", vec!["TEXTURE_2D".to_string()]);
shaders.insert("cs_clip_box_shadow", vec!["TEXTURE_2D".to_string()]);
// Cache shaders
diff --git a/gfx/wr/wr_glyph_rasterizer/Cargo.toml b/gfx/wr/wr_glyph_rasterizer/Cargo.toml
index 1d94a460cc..b06cd0f084 100644
--- a/gfx/wr/wr_glyph_rasterizer/Cargo.toml
+++ b/gfx/wr/wr_glyph_rasterizer/Cargo.toml
@@ -25,7 +25,7 @@ tracy-rs = "0.1.2"
log = "0.4"
lazy_static = "1"
fxhash = "0.2.1"
-glean = { version = "57.0.0", optional = true }
+glean = { version = "58.1.0", optional = true }
firefox-on-glean = { version = "0.1.0", optional = true }
serde = { optional = true, version = "1.0", features = ["serde_derive"] }
@@ -37,14 +37,14 @@ glutin = "0.28"
rayon = "1"
winit = "0.26"
-[target.'cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))'.dependencies]
+[target.'cfg(any(target_os = "android", all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies]
freetype = { version = "0.7", default-features = false }
libc = "0.2"
[target.'cfg(target_os = "windows")'.dependencies]
dwrote = "0.11"
-[target.'cfg(target_os = "macos")'.dependencies]
+[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
core-foundation = "0.9.2"
core-graphics = "0.23"
core-text = { version = "20.1", default-features = false }
diff --git a/gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs b/gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs
index 15075bacbf..82555c8a06 100644
--- a/gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs
+++ b/gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs
@@ -168,7 +168,7 @@ impl ColorLut for ColorU {
// so we can get linear values.
// CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value.
// The color space used does not appear to affect this choice.
-#[cfg(target_os="macos")]
+#[cfg(any(target_os="macos", target_os = "ios"))]
fn get_inverse_gamma_table_coregraphics_smoothing() -> [u8; 256] {
let mut table = [0u8; 256];
@@ -250,7 +250,7 @@ pub fn build_gamma_correcting_lut(table: &mut [u8; 256], src: u8, contrast: f32,
pub struct GammaLut {
tables: [[u8; 256]; 1 << LUM_BITS],
- #[cfg(target_os="macos")]
+ #[cfg(any(target_os="macos", target_os="ios"))]
cg_inverse_gamma: [u8; 256],
}
@@ -280,12 +280,12 @@ impl GammaLut {
}
pub fn new(contrast: f32, paint_gamma: f32, device_gamma: f32) -> GammaLut {
- #[cfg(target_os="macos")]
+ #[cfg(any(target_os="macos", target_os="ios"))]
let mut table = GammaLut {
tables: [[0; 256]; 1 << LUM_BITS],
cg_inverse_gamma: get_inverse_gamma_table_coregraphics_smoothing(),
};
- #[cfg(not(target_os="macos"))]
+ #[cfg(not(any(target_os="macos", target_os="ios")))]
let mut table = GammaLut {
tables: [[0; 256]; 1 << LUM_BITS],
};
@@ -337,7 +337,7 @@ impl GammaLut {
}
}
- #[cfg(target_os="macos")]
+ #[cfg(any(target_os="macos", target_os="ios"))]
pub fn coregraphics_convert_to_linear(&self, pixels: &mut [u8]) {
for pixel in pixels.chunks_mut(4) {
pixel[0] = self.cg_inverse_gamma[pixel[0] as usize];
diff --git a/gfx/wr/wr_glyph_rasterizer/src/lib.rs b/gfx/wr/wr_glyph_rasterizer/src/lib.rs
index 27ceb71992..3cf95d7c31 100644
--- a/gfx/wr/wr_glyph_rasterizer/src/lib.rs
+++ b/gfx/wr/wr_glyph_rasterizer/src/lib.rs
@@ -9,7 +9,7 @@
//! ## Usage
//!
-#[cfg(any(target_os = "macos", target_os = "windows"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "windows"))]
mod gamma_lut;
mod rasterizer;
mod telemetry;
@@ -38,18 +38,18 @@ extern crate serde;
extern crate malloc_size_of;
pub mod platform {
- #[cfg(target_os = "macos")]
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
pub use crate::platform::macos::font;
- #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
+ #[cfg(any(target_os = "android", all(unix, not(any(target_os = "ios", target_os = "macos")))))]
pub use crate::platform::unix::font;
#[cfg(target_os = "windows")]
pub use crate::platform::windows::font;
- #[cfg(target_os = "macos")]
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
pub mod macos {
pub mod font;
}
- #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
+ #[cfg(any(target_os = "android", all(unix, not(any(target_os = "macos", target_os = "ios")))))]
pub mod unix {
pub mod font;
}