Update On Mon Feb 26 19:42:19 CET 2024

This commit is contained in:
github-action[bot] 2024-02-26 19:42:19 +01:00
parent 3d2961ec46
commit b19f1b34aa
214 changed files with 2393 additions and 962 deletions

1
Cargo.lock generated
View file

@ -6549,6 +6549,7 @@ dependencies = [
name = "wgpu_bindings"
version = "0.1.0"
dependencies = [
"arrayvec",
"bincode",
"d3d12",
"log",

View file

@ -124,7 +124,6 @@ module.exports = {
"consistent-this": ["error", "use-bind"],
eqeqeq: "error",
"func-name-matching": "error",
"getter-return": "error",
"guard-for-in": "error",
"max-nested-callbacks": ["error", 4],
"max-params": ["error", 6],

View file

@ -94,7 +94,6 @@ module.exports = {
"consistent-this": ["error", "use-bind"],
eqeqeq: "error",
"func-name-matching": "error",
"getter-return": "error",
"guard-for-in": "error",
"max-nested-callbacks": ["error", 4],
"max-params": ["error", 6],

View file

@ -123,7 +123,6 @@ module.exports = {
"consistent-this": ["error", "use-bind"],
eqeqeq: "error",
"func-name-matching": "error",
"getter-return": "error",
"guard-for-in": "error",
"max-nested-callbacks": ["error", 4],
"max-params": ["error", 6],

View file

@ -558,11 +558,17 @@ class MenuHelper {
return true;
}
get reportBrokenSite() {}
get reportBrokenSite() {
throw new Error("Should be defined in derived class");
}
get reportSiteIssue() {}
get reportSiteIssue() {
throw new Error("Should be defined in derived class");
}
get popup() {}
get popup() {
throw new Error("Should be defined in derived class");
}
get opened() {
return this.popup?.hasAttribute("panelopen");

View file

@ -20,8 +20,6 @@ skip-if = ["apple_silicon && !debug"]
["browser_fr_fields.js"]
["browser_ignore_unfocusable_fields.js"]
["browser_label_rules.js"]
["browser_multiple_section.js"]
@ -37,3 +35,5 @@ skip-if = ["apple_silicon && !debug"]
["browser_section_validation_address.js"]
["browser_sections_by_name.js"]
["browser_sections_with_invisible_fields.js"]

View file

@ -1,159 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* global add_heuristic_tests */
"use strict";
add_heuristic_tests([
{
description: "All visual fields are considered focusable.",
fixtureData: `
<html>
<body>
<form>
<input type="text" id="name" autocomplete="name" />
<input type="text" id="tel" autocomplete="tel" />
<input type="text" id="email" autocomplete="email"/>
<select id="country" autocomplete="country">
<option value="United States">United States</option>
</select>
<input type="text" id="postal-code" autocomplete="postal-code"/>
<input type="text" id="address-line1" autocomplete="address-line1" />
<div>
<input type="text" id="address-line2" autocomplete="address-line2" />
</div>
</form>
</form>
</body>
</html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "name" },
{ fieldName: "tel" },
{ fieldName: "email" },
{ fieldName: "country" },
{ fieldName: "postal-code" },
{ fieldName: "address-line1" },
{ fieldName: "address-line2" },
],
},
],
},
{
// ignore opacity (see Bug 1835852),
description:
"Invisible fields with style.opacity=0 set are considered focusable.",
fixtureData: `
<html>
<body>
<form>
<input type="text" id="name" autocomplete="name" style="opacity:0" />
<input type="text" id="tel" autocomplete="tel" />
<input type="text" id="email" autocomplete="email" style="opacity:0"/>
<select id="country" autocomplete="country">
<option value="United States">United States</option>
</select>
<input type="text" id="postal-code" autocomplete="postal-code" />
<input type="text" id="address-line1" autocomplete="address-line1" />
<div>
<input type="text" id="address-line2" autocomplete="address-line2" />
</div>
</form>
</form>
</body>
</html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "name" },
{ fieldName: "tel" },
{ fieldName: "email" },
{ fieldName: "country" },
{ fieldName: "postal-code" },
{ fieldName: "address-line1" },
{ fieldName: "address-line2" },
],
},
],
},
{
description:
"Some fields are considered unfocusable due to their invisibility.",
fixtureData: `
<html>
<body>
<form>
<input type="text" id="name" autocomplete="name" />
<input type="text" id="tel" autocomplete="tel" />
<input type="text" id="email" autocomplete="email" />
<input type="text" id="country" autocomplete="country" />
<input type="text" id="postal-code" autocomplete="postal-code" hidden />
<input type="text" id="address-line1" autocomplete="address-line1" style="display:none" />
<div style="visibility: hidden">
<input type="text" id="address-line2" autocomplete="address-line2" />
</div>
</form>
</body>
</html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "name" },
{ fieldName: "tel" },
{ fieldName: "email" },
{ fieldName: "country" },
],
},
],
},
{
description: `Disabled field and field with tabindex="-1" is considered unfocusable`,
fixtureData: `
<html>
<body>
<form>
<input type="text" id="name" autocomplete="name" />
<input type="text" id="tel" autocomplete="tel" />
<input type="text" id="email" autocomplete="email" />
<input type="text" id="country" autocomplete="country" disabled/>
<input type="text" id="postal-code" autocomplete="postal-code" tabindex="-1"/>
<input type="text" id="address-line1" autocomplete="address-line1" />
<input type="text" id="address-line2" autocomplete="address-line2" />
</form>
</body>
</html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "name" },
{ fieldName: "tel" },
{ fieldName: "email" },
{ fieldName: "address-line1" },
{ fieldName: "address-line2" },
],
},
],
},
]);

View file

@ -0,0 +1,131 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* global add_heuristic_tests */
"use strict";
add_heuristic_tests([
{
description: `Create a new section when the section already has a field with the same field name`,
fixtureData: `
<html><body>
<input type="text" autocomplete="cc-number"/>
<input type="text" autocomplete="cc-name"/>
<input type="text" autocomplete="cc-exp"/>
<input type="text" autocomplete="cc-exp"/>
</body></html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "cc-number" },
{ fieldName: "cc-name" },
{ fieldName: "cc-exp" },
],
},
{
fields: [{ fieldName: "cc-exp", reason: "autocomplete" }],
},
],
},
{
description: `Do not create a new section for an invisible field`,
fixtureData: `
<html><body>
<input type="text" autocomplete="cc-number"/>
<input type="text" autocomplete="cc-name"/>
<input type="text" autocomplete="cc-exp"/>
<input type="text" autocomplete="cc-exp" style="display:none"/>
</body></html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "cc-number" },
{ fieldName: "cc-name" },
{ fieldName: "cc-exp" },
{ fieldName: "cc-exp" },
],
},
],
},
{
description: `Do not create a new section when the field with the same field name is an invisible field`,
fixtureData: `
<html><body>
<input type="text" autocomplete="cc-number""/>
<input type="text" autocomplete="cc-name"/>
<input type="text" autocomplete="cc-exp" style="display:none"/>
<input type="text" autocomplete="cc-exp"/>
</body></html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "cc-number" },
{ fieldName: "cc-name" },
{ fieldName: "cc-exp" },
{ fieldName: "cc-exp" },
],
},
],
},
{
description: `Do not create a new section for an invisible field (match field is not adjacent)`,
fixtureData: `
<html><body>
<input type="text" autocomplete="cc-number"/>
<input type="text" autocomplete="cc-name"/>
<input type="text" autocomplete="cc-exp"/>
<input type="text" autocomplete="cc-number" style="display:none"/>
</body></html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "cc-number" },
{ fieldName: "cc-name" },
{ fieldName: "cc-exp" },
{ fieldName: "cc-number" },
],
},
],
},
{
description: `Do not create a new section when the field with the same field name is an invisible field (match field is not adjacent)`,
fixtureData: `
<html><body>
<input type="text" autocomplete="cc-number" style="display:none"/>
<input type="text" autocomplete="cc-name"/>
<input type="text" autocomplete="cc-exp"/>
<input type="text" autocomplete="cc-number"/>
</body></html>
`,
expectedResult: [
{
default: {
reason: "autocomplete",
},
fields: [
{ fieldName: "cc-number" },
{ fieldName: "cc-name" },
{ fieldName: "cc-exp" },
{ fieldName: "cc-number" },
],
},
],
},
]);

View file

@ -16,6 +16,8 @@ add_heuristic_tests(
//{ fieldName: "cc-cvc" },
{ fieldName: "cc-exp-month" },
{ fieldName: "cc-exp-year" },
{ fieldName: "cc-number", reason: "regex-heuristic" }, // invisible
{ fieldName: "cc-number", reason: "regex-heuristic" }, // invisible
],
},
{

View file

@ -35,9 +35,16 @@ add_heuristic_tests(
reason: "autocomplete",
},
fields: [
{ fieldName: "cc-exp-month" },
{ fieldName: "cc-exp-year" },
{ fieldName: "cc-number", reason: "fathom" },
{ fieldName: "cc-exp-month", reason: "regex-heuristic" },
{ fieldName: "cc-exp-year", reason: "regex-heuristic" },
],
},
{
invalid: true,
fields: [
{ fieldName: "cc-exp-month", reason: "regex-heuristic" }, // invisible
{ fieldName: "cc-exp-year", reason: "regex-heuristic" }, // invisible
],
},
],

View file

@ -71,24 +71,6 @@ region-name-tw = Taiwan
L10nRegistry.getInstance().registerSources([mockSource]);
}
/**
* Mock the return value of Services.focus.elementIsFocusable
* since a field's focusability can't be tested in a unit test.
*/
(function ignoreAFieldsFocusability() {
let stub = sinon.stub(Services, "focus").get(() => {
return {
elementIsFocusable() {
return true;
},
};
});
registerCleanupFunction(() => {
stub.restore();
});
})();
do_get_profile();
const EXTENSION_ID = "formautofill@mozilla.org";

View file

@ -421,6 +421,39 @@ const TESTCASES = [
"cc-exp-year": "25",
},
},
{
description:
"Form with hidden input and visible input that share the same autocomplete attribute",
document: `<form>
<input id="hidden-cc" autocomplete="cc-number" hidden>
<input id="hidden-cc-2" autocomplete="cc-number" style="display:none">
<input id="visible-cc" autocomplete="cc-number">
<input id="hidden-name" autocomplete="cc-name" hidden>
<input id="hidden-name-2" autocomplete="cc-name" style="display:none">
<input id="visible-name" autocomplete="cc-name">
<input id="cc-exp-month" autocomplete="cc-exp-month">
<input id="cc-exp-year" autocomplete="cc-exp-year">
</form>`,
focusedInputId: "visible-cc",
profileData: {
guid: "123",
"cc-number": "4111111111111111",
"cc-name": "test name",
"cc-exp-month": 6,
"cc-exp-year": 25,
},
expectedResult: {
guid: "123",
"visible-cc": "4111111111111111",
"visible-name": "test name",
"cc-exp-month": "06",
"cc-exp-year": "25",
"hidden-cc": "4111111111111111",
"hidden-cc-2": "4111111111111111",
"hidden-name": "test name",
"hidden-name-2": "test name",
},
},
{
description:
"Fill credit card fields in a form where the value property is being used as a placeholder for cardholder name",

View file

@ -6,6 +6,9 @@ skip-if = [
firefox-appdir = "browser"
head = "head.js"
support-files = ["../fixtures/**"]
prefs = [
"extensions.formautofill.test.ignoreVisibilityCheck=true",
]
["test_activeStatus.js"]

View file

@ -519,7 +519,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "9b0d458004c01cd5ad33d0bf7574a662b1fb06bf"
"revision": "f5fa929f511c8f87161b973d05788492cb64bfeb"
},
"es-MX": {
"pin": false,
@ -861,7 +861,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "d78edcbca24f7d3c10f8d63fec4918cc7e4e7b88"
"revision": "f19469d560a9371766769d32c955c122788a8850"
},
"hy-AM": {
"pin": false,
@ -1353,7 +1353,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "7da781a8d4e2461eae5391371fb848ebc61931d2"
"revision": "786c4f4f659fe3aa92dc6ac4b22ad19c74cb2b4e"
},
"oc": {
"pin": false,
@ -1605,7 +1605,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "df4417ab0f80a1efebae366ef36e6d4a651fefb7"
"revision": "b76336ce9e5c795ffb6db603a8c8bd0490ffeea2"
},
"skr": {
"pin": false,

View file

@ -130,3 +130,12 @@ So pushing to try is basically just:
Because of the build process, a full opt build will take around 1h45-2h while a
debug build will be around 60 minutes, the difference coming from the use of
PGO on opt builds.
If you need to reuse a package from the Snap Store or from the latest
mozilla-central or a specific successful build, you can use ``USE_SNAP_FROM_STORE_OR_MC`` en
variable ; setting it to ``store`` will download from the Snap Store (warning:
no debug builds on the Snap Store, so whatever ``debug`` variants we have will
be an ``opt`` build in fact), and setting to a TaskCluster index value will
download from the index. Set it to ``latest`` if you want latest, or explore
the TaskCluster index for others. Any ``try`` will be pulled from latest
``nightly`` while others will be fetched from their respective branches.

View file

@ -20,9 +20,9 @@ from mozfile import NamedTemporaryFile, TemporaryDirectory
from mozprofile.permissions import ServerLocations
dbFiles = [
re.compile("^cert[0-9]+\.db$"),
re.compile("^key[0-9]+\.db$"),
re.compile("^secmod\.db$"),
re.compile(r"^cert[0-9]+\.db$"),
re.compile(r"^key[0-9]+\.db$"),
re.compile(r"^secmod\.db$"),
]
@ -77,7 +77,7 @@ def writeCertspecForServerLocations(fd):
i for i in iter(locations) if i.scheme == "https" and "nocert" not in i.options
]:
customCertOption = False
customCertRE = re.compile("^cert=(?:\w+)")
customCertRE = re.compile(r"^cert=(?:\w+)")
for _ in [i for i in loc.options if customCertRE.match(i)]:
customCertOption = True
break

View file

@ -132,8 +132,6 @@ module.exports = {
"no-cond-assign": 2,
// Allow using the console API.
"no-console": 0,
// Allow using constant expressions in conditions like while (true)
"no-constant-condition": 0,
// Allow use of the continue statement.
"no-continue": 0,
// Disallow control characters in regular expressions.

View file

@ -73,14 +73,6 @@ DevToolsServerConnection.prototype = {
return this._prefix;
},
/**
* For a DevToolsServerConnection used in content processes,
* returns the prefix of the connection it originates from, from the parent process.
*/
get parentPrefix() {
this.prefix.replace(/child\d+\//, "");
},
_transport: null,
get transport() {
return this._transport;

View file

@ -48,7 +48,7 @@ def filter_git_changes(github_path, commit_sha, diff_filter):
# out the excluded directory paths (note the lack of trailing '$'
# in the regex).
regex_excludes = "|".join(
["^(M|A|D|R\d\d\d)\t{}".format(i) for i in exclude_dir_list]
["^(M|A|D|R\\d\\d\\d)\t{}".format(i) for i in exclude_dir_list]
)
files_not_excluded = [
path for path in changed_files if not re.findall(regex_excludes, path)

View file

@ -52,7 +52,7 @@ def save_patch_stack(
# remove the commit summary from the file name
patches_to_rename = os.listdir(patch_directory)
for file in patches_to_rename:
shortened_name = re.sub("^(\d\d\d\d)-.*\.patch", "\\1.patch", file)
shortened_name = re.sub(r"^(\d\d\d\d)-.*\.patch", "\\1.patch", file)
os.rename(
os.path.join(patch_directory, file),
os.path.join(patch_directory, shortened_name),

View file

@ -175,6 +175,7 @@ add_task(async function testThenableJobAccessError() {
sandbox.thenable = {
get then() {
accessed = true;
return undefined;
},
};

View file

@ -1641,7 +1641,7 @@ let interfaceNamesInGlobalScope = [
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "onbeforeprint", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "onbeforetoggle", insecureContext: true, nightly: true },
{ name: "onbeforetoggle", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "onbeforeunload", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer!

View file

@ -230,24 +230,24 @@ already_AddRefed<RenderPassEncoder> CommandEncoder::BeginRenderPass(
return pass.forget();
}
void CommandEncoder::EndComputePass(ffi::WGPUComputePass& aPass) {
void CommandEncoder::EndComputePass(ffi::WGPURecordedComputePass& aPass) {
if (!mBridge->IsOpen()) {
return;
}
ipc::ByteBuf byteBuf;
ffi::wgpu_compute_pass_finish(&aPass, ToFFI(&byteBuf));
mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(byteBuf));
mBridge->SendComputePass(mId, mParent->mId, std::move(byteBuf));
}
void CommandEncoder::EndRenderPass(ffi::WGPURenderPass& aPass) {
void CommandEncoder::EndRenderPass(ffi::WGPURecordedRenderPass& aPass) {
if (!mBridge->IsOpen()) {
return;
}
ipc::ByteBuf byteBuf;
ffi::wgpu_render_pass_finish(&aPass, ToFFI(&byteBuf));
mBridge->SendCommandEncoderAction(mId, mParent->mId, std::move(byteBuf));
mBridge->SendRenderPass(mId, mParent->mId, std::move(byteBuf));
}
already_AddRefed<CommandBuffer> CommandEncoder::Finish(

View file

@ -32,7 +32,7 @@ using GPUExtent3D = RangeEnforcedUnsignedLongSequenceOrGPUExtent3DDict;
namespace webgpu {
namespace ffi {
struct WGPUComputePass;
struct WGPURenderPass;
struct WGPURecordedRenderPass;
struct WGPUImageDataLayout;
struct WGPUImageCopyTexture_TextureId;
struct WGPUExtent3d;
@ -72,8 +72,8 @@ class CommandEncoder final : public ObjectBase, public ChildOf<Device> {
public:
const auto& GetDevice() const { return mParent; };
void EndComputePass(ffi::WGPUComputePass& aPass);
void EndRenderPass(ffi::WGPURenderPass& aPass);
void EndComputePass(ffi::WGPURecordedComputePass& aPass);
void EndRenderPass(ffi::WGPURecordedRenderPass& aPass);
void CopyBufferToBuffer(const Buffer& aSource, BufferAddress aSourceOffset,
const Buffer& aDestination,

View file

@ -17,13 +17,13 @@ GPU_IMPL_CYCLE_COLLECTION(ComputePassEncoder, mParent, mUsedBindGroups,
mUsedPipelines)
GPU_IMPL_JS_WRAP(ComputePassEncoder)
void ffiWGPUComputePassDeleter::operator()(ffi::WGPUComputePass* raw) {
void ffiWGPUComputePassDeleter::operator()(ffi::WGPURecordedComputePass* raw) {
if (raw) {
ffi::wgpu_compute_pass_destroy(raw);
}
}
ffi::WGPUComputePass* BeginComputePass(
ffi::WGPURecordedComputePass* BeginComputePass(
RawId aEncoderId, const dom::GPUComputePassDescriptor& aDesc) {
MOZ_RELEASE_ASSERT(aEncoderId);
ffi::WGPUComputePassDescriptor desc = {};
@ -31,7 +31,7 @@ ffi::WGPUComputePass* BeginComputePass(
webgpu::StringHelper label(aDesc.mLabel);
desc.label = label.Get();
return ffi::wgpu_command_encoder_begin_compute_pass(aEncoderId, &desc);
return ffi::wgpu_command_encoder_begin_compute_pass(&desc);
}
ComputePassEncoder::ComputePassEncoder(
@ -49,16 +49,16 @@ void ComputePassEncoder::SetBindGroup(
const dom::Sequence<uint32_t>& aDynamicOffsets) {
if (mValid) {
mUsedBindGroups.AppendElement(&aBindGroup);
ffi::wgpu_compute_pass_set_bind_group(mPass.get(), aSlot, aBindGroup.mId,
aDynamicOffsets.Elements(),
aDynamicOffsets.Length());
ffi::wgpu_recorded_compute_pass_set_bind_group(
mPass.get(), aSlot, aBindGroup.mId, aDynamicOffsets.Elements(),
aDynamicOffsets.Length());
}
}
void ComputePassEncoder::SetPipeline(const ComputePipeline& aPipeline) {
if (mValid) {
mUsedPipelines.AppendElement(&aPipeline);
ffi::wgpu_compute_pass_set_pipeline(mPass.get(), aPipeline.mId);
ffi::wgpu_recorded_compute_pass_set_pipeline(mPass.get(), aPipeline.mId);
}
}
@ -66,7 +66,7 @@ void ComputePassEncoder::DispatchWorkgroups(uint32_t workgroupCountX,
uint32_t workgroupCountY,
uint32_t workgroupCountZ) {
if (mValid) {
ffi::wgpu_compute_pass_dispatch_workgroups(
ffi::wgpu_recorded_compute_pass_dispatch_workgroups(
mPass.get(), workgroupCountX, workgroupCountY, workgroupCountZ);
}
}
@ -74,7 +74,7 @@ void ComputePassEncoder::DispatchWorkgroups(uint32_t workgroupCountX,
void ComputePassEncoder::DispatchWorkgroupsIndirect(
const Buffer& aIndirectBuffer, uint64_t aIndirectOffset) {
if (mValid) {
ffi::wgpu_compute_pass_dispatch_workgroups_indirect(
ffi::wgpu_recorded_compute_pass_dispatch_workgroups_indirect(
mPass.get(), aIndirectBuffer.mId, aIndirectOffset);
}
}
@ -82,18 +82,20 @@ void ComputePassEncoder::DispatchWorkgroupsIndirect(
void ComputePassEncoder::PushDebugGroup(const nsAString& aString) {
if (mValid) {
const NS_ConvertUTF16toUTF8 utf8(aString);
ffi::wgpu_compute_pass_push_debug_group(mPass.get(), utf8.get(), 0);
ffi::wgpu_recorded_compute_pass_push_debug_group(mPass.get(), utf8.get(),
0);
}
}
void ComputePassEncoder::PopDebugGroup() {
if (mValid) {
ffi::wgpu_compute_pass_pop_debug_group(mPass.get());
ffi::wgpu_recorded_compute_pass_pop_debug_group(mPass.get());
}
}
void ComputePassEncoder::InsertDebugMarker(const nsAString& aString) {
if (mValid) {
const NS_ConvertUTF16toUTF8 utf8(aString);
ffi::wgpu_compute_pass_insert_debug_marker(mPass.get(), utf8.get(), 0);
ffi::wgpu_recorded_compute_pass_insert_debug_marker(mPass.get(), utf8.get(),
0);
}
}

View file

@ -18,7 +18,7 @@ struct GPUComputePassDescriptor;
namespace webgpu {
namespace ffi {
struct WGPUComputePass;
struct WGPURecordedComputePass;
} // namespace ffi
class BindGroup;
@ -27,7 +27,7 @@ class CommandEncoder;
class ComputePipeline;
struct ffiWGPUComputePassDeleter {
void operator()(ffi::WGPUComputePass*);
void operator()(ffi::WGPURecordedComputePass*);
};
class ComputePassEncoder final : public ObjectBase,
@ -43,7 +43,8 @@ class ComputePassEncoder final : public ObjectBase,
virtual ~ComputePassEncoder();
void Cleanup() {}
std::unique_ptr<ffi::WGPUComputePass, ffiWGPUComputePassDeleter> mPass;
std::unique_ptr<ffi::WGPURecordedComputePass, ffiWGPUComputePassDeleter>
mPass;
// keep all the used objects alive while the pass is recorded
nsTArray<RefPtr<const BindGroup>> mUsedBindGroups;
nsTArray<RefPtr<const ComputePipeline>> mUsedPipelines;

View file

@ -18,7 +18,7 @@ GPU_IMPL_CYCLE_COLLECTION(RenderPassEncoder, mParent, mUsedBindGroups,
mUsedRenderBundles)
GPU_IMPL_JS_WRAP(RenderPassEncoder)
void ffiWGPURenderPassDeleter::operator()(ffi::WGPURenderPass* raw) {
void ffiWGPURenderPassDeleter::operator()(ffi::WGPURecordedRenderPass* raw) {
if (raw) {
ffi::wgpu_render_pass_destroy(raw);
}
@ -87,7 +87,7 @@ static ffi::WGPUColor ConvertColor(
return ffi::WGPUColor();
}
ffi::WGPURenderPass* BeginRenderPass(
ffi::WGPURecordedRenderPass* BeginRenderPass(
CommandEncoder* const aParent, const dom::GPURenderPassDescriptor& aDesc) {
ffi::WGPURenderPassDescriptor desc = {};
@ -155,7 +155,7 @@ ffi::WGPURenderPass* BeginRenderPass(
}
}
return ffi::wgpu_command_encoder_begin_render_pass(aParent->mId, &desc);
return ffi::wgpu_command_encoder_begin_render_pass(&desc);
}
RenderPassEncoder::RenderPassEncoder(CommandEncoder* const aParent,
@ -186,16 +186,16 @@ void RenderPassEncoder::SetBindGroup(
const dom::Sequence<uint32_t>& aDynamicOffsets) {
if (mValid) {
mUsedBindGroups.AppendElement(&aBindGroup);
ffi::wgpu_render_pass_set_bind_group(mPass.get(), aSlot, aBindGroup.mId,
aDynamicOffsets.Elements(),
aDynamicOffsets.Length());
ffi::wgpu_recorded_render_pass_set_bind_group(
mPass.get(), aSlot, aBindGroup.mId, aDynamicOffsets.Elements(),
aDynamicOffsets.Length());
}
}
void RenderPassEncoder::SetPipeline(const RenderPipeline& aPipeline) {
if (mValid) {
mUsedPipelines.AppendElement(&aPipeline);
ffi::wgpu_render_pass_set_pipeline(mPass.get(), aPipeline.mId);
ffi::wgpu_recorded_render_pass_set_pipeline(mPass.get(), aPipeline.mId);
}
}
@ -207,8 +207,8 @@ void RenderPassEncoder::SetIndexBuffer(const Buffer& aBuffer,
const auto iformat = aIndexFormat == dom::GPUIndexFormat::Uint32
? ffi::WGPUIndexFormat_Uint32
: ffi::WGPUIndexFormat_Uint16;
ffi::wgpu_render_pass_set_index_buffer(mPass.get(), aBuffer.mId, iformat,
aOffset, aSize);
ffi::wgpu_recorded_render_pass_set_index_buffer(mPass.get(), aBuffer.mId,
iformat, aOffset, aSize);
}
}
@ -216,16 +216,17 @@ void RenderPassEncoder::SetVertexBuffer(uint32_t aSlot, const Buffer& aBuffer,
uint64_t aOffset, uint64_t aSize) {
if (mValid) {
mUsedBuffers.AppendElement(&aBuffer);
ffi::wgpu_render_pass_set_vertex_buffer(mPass.get(), aSlot, aBuffer.mId,
aOffset, aSize);
ffi::wgpu_recorded_render_pass_set_vertex_buffer(
mPass.get(), aSlot, aBuffer.mId, aOffset, aSize);
}
}
void RenderPassEncoder::Draw(uint32_t aVertexCount, uint32_t aInstanceCount,
uint32_t aFirstVertex, uint32_t aFirstInstance) {
if (mValid) {
ffi::wgpu_render_pass_draw(mPass.get(), aVertexCount, aInstanceCount,
aFirstVertex, aFirstInstance);
ffi::wgpu_recorded_render_pass_draw(mPass.get(), aVertexCount,
aInstanceCount, aFirstVertex,
aFirstInstance);
}
}
@ -234,24 +235,24 @@ void RenderPassEncoder::DrawIndexed(uint32_t aIndexCount,
uint32_t aFirstIndex, int32_t aBaseVertex,
uint32_t aFirstInstance) {
if (mValid) {
ffi::wgpu_render_pass_draw_indexed(mPass.get(), aIndexCount, aInstanceCount,
aFirstIndex, aBaseVertex,
aFirstInstance);
ffi::wgpu_recorded_render_pass_draw_indexed(mPass.get(), aIndexCount,
aInstanceCount, aFirstIndex,
aBaseVertex, aFirstInstance);
}
}
void RenderPassEncoder::DrawIndirect(const Buffer& aIndirectBuffer,
uint64_t aIndirectOffset) {
if (mValid) {
ffi::wgpu_render_pass_draw_indirect(mPass.get(), aIndirectBuffer.mId,
aIndirectOffset);
ffi::wgpu_recorded_render_pass_draw_indirect(
mPass.get(), aIndirectBuffer.mId, aIndirectOffset);
}
}
void RenderPassEncoder::DrawIndexedIndirect(const Buffer& aIndirectBuffer,
uint64_t aIndirectOffset) {
if (mValid) {
ffi::wgpu_render_pass_draw_indexed_indirect(
ffi::wgpu_recorded_render_pass_draw_indexed_indirect(
mPass.get(), aIndirectBuffer.mId, aIndirectOffset);
}
}
@ -259,15 +260,16 @@ void RenderPassEncoder::DrawIndexedIndirect(const Buffer& aIndirectBuffer,
void RenderPassEncoder::SetViewport(float x, float y, float width, float height,
float minDepth, float maxDepth) {
if (mValid) {
ffi::wgpu_render_pass_set_viewport(mPass.get(), x, y, width, height,
minDepth, maxDepth);
ffi::wgpu_recorded_render_pass_set_viewport(mPass.get(), x, y, width,
height, minDepth, maxDepth);
}
}
void RenderPassEncoder::SetScissorRect(uint32_t x, uint32_t y, uint32_t width,
uint32_t height) {
if (mValid) {
ffi::wgpu_render_pass_set_scissor_rect(mPass.get(), x, y, width, height);
ffi::wgpu_recorded_render_pass_set_scissor_rect(mPass.get(), x, y, width,
height);
}
}
@ -275,13 +277,14 @@ void RenderPassEncoder::SetBlendConstant(
const dom::DoubleSequenceOrGPUColorDict& color) {
if (mValid) {
ffi::WGPUColor aColor = ConvertColor(color);
ffi::wgpu_render_pass_set_blend_constant(mPass.get(), &aColor);
ffi::wgpu_recorded_render_pass_set_blend_constant(mPass.get(), &aColor);
}
}
void RenderPassEncoder::SetStencilReference(uint32_t reference) {
if (mValid) {
ffi::wgpu_render_pass_set_stencil_reference(mPass.get(), reference);
ffi::wgpu_recorded_render_pass_set_stencil_reference(mPass.get(),
reference);
}
}
@ -293,26 +296,27 @@ void RenderPassEncoder::ExecuteBundles(
mUsedRenderBundles.AppendElement(bundle);
renderBundles.AppendElement(bundle->mId);
}
ffi::wgpu_render_pass_execute_bundles(mPass.get(), renderBundles.Elements(),
renderBundles.Length());
ffi::wgpu_recorded_render_pass_execute_bundles(
mPass.get(), renderBundles.Elements(), renderBundles.Length());
}
}
void RenderPassEncoder::PushDebugGroup(const nsAString& aString) {
if (mValid) {
const NS_ConvertUTF16toUTF8 utf8(aString);
ffi::wgpu_render_pass_push_debug_group(mPass.get(), utf8.get(), 0);
ffi::wgpu_recorded_render_pass_push_debug_group(mPass.get(), utf8.get(), 0);
}
}
void RenderPassEncoder::PopDebugGroup() {
if (mValid) {
ffi::wgpu_render_pass_pop_debug_group(mPass.get());
ffi::wgpu_recorded_render_pass_pop_debug_group(mPass.get());
}
}
void RenderPassEncoder::InsertDebugMarker(const nsAString& aString) {
if (mValid) {
const NS_ConvertUTF16toUTF8 utf8(aString);
ffi::wgpu_render_pass_insert_debug_marker(mPass.get(), utf8.get(), 0);
ffi::wgpu_recorded_render_pass_insert_debug_marker(mPass.get(), utf8.get(),
0);
}
}

View file

@ -24,7 +24,7 @@ class AutoSequence;
} // namespace dom
namespace webgpu {
namespace ffi {
struct WGPURenderPass;
struct WGPURecordedRenderPass;
} // namespace ffi
class BindGroup;
@ -35,7 +35,7 @@ class RenderPipeline;
class TextureView;
struct ffiWGPURenderPassDeleter {
void operator()(ffi::WGPURenderPass*);
void operator()(ffi::WGPURecordedRenderPass*);
};
class RenderPassEncoder final : public ObjectBase,
@ -51,7 +51,7 @@ class RenderPassEncoder final : public ObjectBase,
virtual ~RenderPassEncoder();
void Cleanup() {}
std::unique_ptr<ffi::WGPURenderPass, ffiWGPURenderPassDeleter> mPass;
std::unique_ptr<ffi::WGPURecordedRenderPass, ffiWGPURenderPassDeleter> mPass;
// keep all the used objects alive while the pass is recorded
nsTArray<RefPtr<const BindGroup>> mUsedBindGroups;
nsTArray<RefPtr<const Buffer>> mUsedBuffers;

View file

@ -44,6 +44,8 @@ parent:
async DeviceActionWithAck(RawId selfId, ByteBuf buf) returns (bool dummy);
async TextureAction(RawId selfId, RawId aDeviceId, ByteBuf buf);
async CommandEncoderAction(RawId selfId, RawId aDeviceId, ByteBuf buf);
async RenderPass(RawId selfId, RawId aDeviceId, ByteBuf buf);
async ComputePass(RawId selfId, RawId aDeviceId, ByteBuf buf);
async BumpImplicitBindGroupLayout(RawId pipelineId, bool isCompute, uint32_t index, RawId assignId);
async DeviceCreateBuffer(RawId deviceId, RawId bufferId, GPUBufferDescriptor desc, UnsafeSharedMemoryHandle shm);

View file

@ -1359,6 +1359,24 @@ ipc::IPCResult WebGPUParent::RecvCommandEncoderAction(
return IPC_OK();
}
ipc::IPCResult WebGPUParent::RecvRenderPass(RawId aEncoderId, RawId aDeviceId,
const ipc::ByteBuf& aByteBuf) {
ErrorBuffer error;
ffi::wgpu_server_render_pass(mContext.get(), aEncoderId, ToFFI(&aByteBuf),
error.ToFFI());
ForwardError(aDeviceId, error);
return IPC_OK();
}
ipc::IPCResult WebGPUParent::RecvComputePass(RawId aEncoderId, RawId aDeviceId,
const ipc::ByteBuf& aByteBuf) {
ErrorBuffer error;
ffi::wgpu_server_compute_pass(mContext.get(), aEncoderId, ToFFI(&aByteBuf),
error.ToFFI());
ForwardError(aDeviceId, error);
return IPC_OK();
}
ipc::IPCResult WebGPUParent::RecvBumpImplicitBindGroupLayout(RawId aPipelineId,
bool aIsCompute,
uint32_t aIndex,

View file

@ -118,6 +118,10 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
const ipc::ByteBuf& aByteBuf);
ipc::IPCResult RecvCommandEncoderAction(RawId aEncoderId, RawId aDeviceId,
const ipc::ByteBuf& aByteBuf);
ipc::IPCResult RecvRenderPass(RawId aEncoderId, RawId aDeviceId,
const ipc::ByteBuf& aByteBuf);
ipc::IPCResult RecvComputePass(RawId aEncoderId, RawId aDeviceId,
const ipc::ByteBuf& aByteBuf);
ipc::IPCResult RecvBumpImplicitBindGroupLayout(RawId aPipelineId,
bool aIsCompute,
uint32_t aIndex,

View file

@ -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.

View file

@ -893,6 +893,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;

View file

@ -158,6 +158,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 {
@ -420,9 +423,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);
@ -731,6 +736,8 @@ void APZCTreeManager::UpdateHitTestingTree(
mRootNode->Dump(" ");
}
SendSubtreeTransformsToChromeMainThread(nullptr);
return OriginatingLayersIdUpdated{state.mOriginatingLayersIdUpdated};
}
void APZCTreeManager::UpdateFocusState(LayersId aRootLayerTreeId,
@ -1232,6 +1239,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.

View file

@ -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

View file

@ -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();
}
}));
}

View file

@ -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;

View file

@ -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

View file

@ -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(

View file

@ -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"

View file

@ -770,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,
@ -796,8 +795,7 @@ 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,
let pass = crate::command::RecordedComputePass::new(
&wgc::command::ComputePassDescriptor {
label,
timestamp_writes,
@ -808,15 +806,15 @@ pub unsafe extern "C" fn wgpu_command_encoder_begin_compute_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);
}
@ -839,9 +837,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,
@ -874,8 +871,7 @@ 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,
let pass = crate::command::RecordedRenderPass::new(
&wgc::command::RenderPassDescriptor {
label,
color_attachments: Cow::Owned(color_attachments),
@ -889,15 +885,15 @@ pub unsafe extern "C" fn wgpu_command_encoder_begin_render_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);
}

File diff suppressed because it is too large Load diff

View file

@ -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;

View file

@ -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,
};
@ -580,9 +582,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 +595,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,
@ -1053,6 +1057,32 @@ pub unsafe extern "C" fn wgpu_server_command_encoder_action(
gfx_select!(self_id => global.command_encoder_action(self_id, action, error_buf));
}
#[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,

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
uniform HIGHP_SAMPLER_FLOAT sampler2D sGpuBufferF;
uniform HIGHP_SAMPLER_FLOAT sampler2D sGpuBufferI;
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,
@ -41,3 +41,8 @@ vec4[4] fetch_from_gpu_buffer_4f(HIGHP_FS_ADDRESS int address) {
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);
}

View file

@ -81,37 +81,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 +179,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:

View file

@ -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, GpuBufferBuilderF, 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};
@ -803,7 +803,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 +811,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 +821,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 +859,7 @@ impl BatchBuilder {
surface_spatial_node_index: SpatialNodeIndex,
z_generator: &mut ZBufferIdGenerator,
prim_instances: &[PrimitiveInstance],
_gpu_buffer_builder: &mut GpuBufferBuilderF,
gpu_buffer_builder: &mut GpuBufferBuilder,
segments: &[RenderTaskId],
) {
let (prim_instance_index, extra_prim_gpu_address) = match cmd {
@ -883,6 +885,7 @@ impl BatchBuilder {
z_generator,
prim_instances,
render_tasks,
gpu_buffer_builder,
);
} else {
for (i, task_id) in segments.iter().enumerate() {
@ -900,6 +903,7 @@ impl BatchBuilder {
z_generator,
prim_instances,
render_tasks,
gpu_buffer_builder,
);
}
}
@ -3837,13 +3841,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 +3862,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 +3912,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 +3926,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 +3972,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,

View file

@ -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::{GpuBufferF, GpuBufferBuilderF, GpuBufferI, GpuBufferBuilderI};
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};
@ -171,8 +171,7 @@ pub struct FrameBuildingState<'a> {
pub surface_builder: SurfaceBuilder,
pub cmd_buffers: &'a mut CommandBufferList,
pub clip_tree: &'a ClipTree,
pub frame_gpu_data_f: &'a mut GpuBufferBuilderF,
pub frame_gpu_data_i: &'a mut GpuBufferBuilderI,
pub frame_gpu_data: &'a mut GpuBufferBuilder,
}
impl<'a> FrameBuildingState<'a> {
@ -277,8 +276,7 @@ impl FrameBuilder {
tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
spatial_tree: &SpatialTree,
cmd_buffers: &mut CommandBufferList,
frame_gpu_data_f: &mut GpuBufferBuilderF,
frame_gpu_data_i: &mut GpuBufferBuilderI,
frame_gpu_data: &mut GpuBufferBuilder,
profile: &mut TransactionProfile,
) {
profile_scope!("build_layer_screen_rects_and_cull_layers");
@ -430,8 +428,7 @@ impl FrameBuilder {
surface_builder: SurfaceBuilder::new(),
cmd_buffers,
clip_tree: &mut scene.clip_tree,
frame_gpu_data_f,
frame_gpu_data_i,
frame_gpu_data,
};
// Push a default dirty region which culls primitives
@ -561,8 +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_f = GpuBufferBuilderF::new();
let mut gpu_buffer_builder_i = GpuBufferBuilderI::new();
let mut gpu_buffer_builder = GpuBufferBuilder {
f32: GpuBufferBuilderF::new(),
i32: GpuBufferBuilderI::new(),
};
self.build_layer_screen_rects_and_cull_layers(
scene,
@ -580,8 +579,7 @@ impl FrameBuilder {
tile_caches,
spatial_tree,
&mut cmd_buffers,
&mut gpu_buffer_builder_f,
&mut gpu_buffer_builder_i,
&mut gpu_buffer_builder,
profile,
);
@ -637,7 +635,7 @@ impl FrameBuilder {
output_size,
&mut ctx,
gpu_cache,
&mut gpu_buffer_builder_f,
&mut gpu_buffer_builder,
&render_tasks,
&scene.clip_store,
&mut transform_palette,
@ -695,8 +693,8 @@ impl FrameBuilder {
scene.clip_store.end_frame(&mut scratch.clip_store);
scratch.end_frame();
let gpu_buffer_f = gpu_buffer_builder_f.finalize(&render_tasks);
let gpu_buffer_i = gpu_buffer_builder_i.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(
@ -766,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;
@ -812,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.
@ -827,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);
}
}
});
@ -901,7 +906,7 @@ pub fn build_render_pass(
screen_size: DeviceIntSize,
ctx: &mut RenderTargetContext,
gpu_cache: &mut GpuCache,
gpu_buffer_builder: &mut GpuBufferBuilderF,
gpu_buffer_builder: &mut GpuBufferBuilder,
render_tasks: &RenderTaskGraph,
clip_store: &ClipStore,
transforms: &mut TransformPalette,
@ -974,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 = GpuBufferBuilderF::new();
match task.kind {
RenderTaskKind::Picture(ref pic_task) => {
@ -1005,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,
);
});
@ -1079,6 +1083,7 @@ pub fn build_render_pass(
z_generator,
prim_instances,
cmd_buffers,
gpu_buffer_builder,
);
pass.alpha.build(
ctx,
@ -1089,6 +1094,7 @@ pub fn build_render_pass(
z_generator,
prim_instances,
cmd_buffers,
gpu_buffer_builder,
);
pass

View file

@ -547,7 +547,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 +560,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.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 as i32,
((instance.part_index as i32) << 24) | instance.z_id.0,
((instance.segment_index as i32) << 24) | instance.transform_id.0 as i32,
],
}
}

View file

@ -452,7 +452,7 @@ fn prepare_interned_prim_for_render(
kind: RenderTaskCacheKeyKind::LineDecoration(cache_key.clone()),
},
frame_state.gpu_cache,
frame_state.frame_gpu_data_f,
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,
@ -607,7 +607,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_f,
&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 +764,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_f,
&mut frame_state.frame_gpu_data.f32,
prim_data.common.prim_rect,
prim_instance.vis.clip_chain.local_clip_rect,
premul_color,
@ -1138,7 +1138,7 @@ fn prepare_interned_prim_for_render(
let stops_address = GradientGpuBlockBuilder::build(
prim_data.reverse_stops,
frame_state.frame_gpu_data_f,
&mut frame_state.frame_gpu_data.f32,
&prim_data.stops,
);
@ -1296,8 +1296,8 @@ fn prepare_interned_prim_for_render(
.clipped_local_rect
.cast_unit();
let main_prim_address = write_prim_blocks(
frame_state.frame_gpu_data_f,
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 +1333,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
@ -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);
@ -1820,7 +1820,7 @@ pub fn update_clip_task(
root_spatial_node_index,
frame_state.clip_store,
frame_state.gpu_cache,
frame_state.frame_gpu_data_f,
&mut frame_state.frame_gpu_data.f32,
frame_state.resource_cache,
frame_state.rg_builder,
&mut data_stores.clip,
@ -1881,7 +1881,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_f,
&mut frame_state.frame_gpu_data.f32,
frame_state.resource_cache,
frame_state.rg_builder,
clip_data_store,
@ -2153,7 +2153,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 +2177,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 +2189,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 +2223,7 @@ fn add_composite_prim(
segments: &[QuadSegment],
) {
let composite_prim_address = write_prim_blocks(
frame_state.frame_gpu_data_f,
&mut frame_state.frame_gpu_data.f32,
rect,
rect,
color,

View file

@ -254,7 +254,7 @@ impl ConicGradientTemplate {
kind: RenderTaskCacheKeyKind::ConicGradient(cache_key),
},
frame_state.gpu_cache,
frame_state.frame_gpu_data_f,
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,

View file

@ -522,7 +522,7 @@ impl LinearGradientTemplate {
kind: RenderTaskCacheKeyKind::FastLinearGradient(gradient),
},
frame_state.gpu_cache,
frame_state.frame_gpu_data_f,
&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_f,
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,

View file

@ -220,7 +220,7 @@ impl RadialGradientTemplate {
kind: RenderTaskCacheKeyKind::RadialGradient(cache_key),
},
frame_state.gpu_cache,
frame_state.frame_gpu_data_f,
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
false,

View file

@ -257,7 +257,7 @@ impl ImageData {
kind: RenderTaskCacheKeyKind::Image(image_cache_key),
},
frame_state.gpu_cache,
frame_state.frame_gpu_data_f,
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
None,
descriptor.is_opaque(),

View file

@ -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,

View file

@ -24,7 +24,7 @@ use crate::prim_store::gradient::{
FastLinearGradientInstance, LinearGradientInstance, RadialGradientInstance,
ConicGradientInstance,
};
use crate::renderer::{GpuBufferBuilderF, 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,
) {
}
@ -121,7 +122,7 @@ pub trait RenderTarget {
task_id: RenderTaskId,
ctx: &RenderTargetContext,
gpu_cache: &mut GpuCache,
gpu_buffer_builder: &mut GpuBufferBuilderF,
gpu_buffer_builder: &mut GpuBufferBuilder,
render_tasks: &RenderTaskGraph,
clip_store: &ClipStore,
transforms: &mut TransformPalette,
@ -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 = GpuBufferBuilderF::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,
);
});
@ -360,7 +363,7 @@ impl RenderTarget for ColorRenderTarget {
task_id: RenderTaskId,
ctx: &RenderTargetContext,
gpu_cache: &mut GpuCache,
gpu_buffer_builder: &mut GpuBufferBuilderF,
gpu_buffer_builder: &mut GpuBufferBuilder,
render_tasks: &RenderTaskGraph,
_: &ClipStore,
transforms: &mut TransformPalette,
@ -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
@ -528,7 +532,7 @@ impl RenderTarget for AlphaRenderTarget {
task_id: RenderTaskId,
ctx: &RenderTargetContext,
gpu_cache: &mut GpuCache,
gpu_buffer_builder: &mut GpuBufferBuilderF,
gpu_buffer_builder: &mut GpuBufferBuilder,
render_tasks: &RenderTaskGraph,
clip_store: &ClipStore,
transforms: &mut TransformPalette,
@ -966,7 +970,7 @@ fn build_mask_tasks(
clip_store: &ClipStore,
data_stores: &DataStores,
spatial_tree: &SpatialTree,
gpu_buffer_builder: &mut GpuBufferBuilderF,
gpu_buffer_builder: &mut GpuBufferBuilder,
transforms: &mut TransformPalette,
render_tasks: &RenderTaskGraph,
results: &mut ClipMaskInstanceList,
@ -978,7 +982,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 +990,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 +1015,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 +1047,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 +1071,7 @@ fn build_mask_tasks(
tile.task_id,
ZBufferId(0),
render_tasks,
gpu_buffer_builder,
|_, prim| {
if clip_needs_scissor_rect {
results
@ -1107,7 +1112,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 +1167,7 @@ fn build_mask_tasks(
RenderTaskId::INVALID,
ZBufferId(0),
render_tasks,
gpu_buffer_builder,
|_, prim| {
let instance = MaskInstance {
prim,
@ -1198,7 +1204,7 @@ fn build_mask_tasks(
fn build_sub_pass(
task_id: RenderTaskId,
task: &RenderTask,
gpu_buffer_builder: &mut GpuBufferBuilderF,
gpu_buffer_builder: &mut GpuBufferBuilder,
render_tasks: &RenderTaskGraph,
transforms: &mut TransformPalette,
ctx: &RenderTargetContext,
@ -1235,7 +1241,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,

View file

@ -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,
@ -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))]

View file

@ -17,11 +17,16 @@ 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 = GpuBufferBuilder<GpuBufferBlockF>;
pub type GpuBufferBuilderF = GpuBufferBuilderImpl<GpuBufferBlockF>;
pub type GpuBufferI = GpuBuffer<GpuBufferBlockI>;
pub type GpuBufferBuilderI = GpuBufferBuilder<GpuBufferBlockI>;
pub type GpuBufferBuilderI = GpuBufferBuilderImpl<GpuBufferBlockI>;
unsafe impl Texel for GpuBufferBlockF {
fn image_format() -> ImageFormat { ImageFormat::RGBAF32 }
@ -173,6 +178,14 @@ impl Into<GpuBufferBlockF> for [f32; 4] {
}
}
impl Into<GpuBufferBlockI> for [i32; 4] {
fn into(self) -> GpuBufferBlockI {
GpuBufferBlockI {
data: self,
}
}
}
/// Record a patch to the GPU buffer for a render task
struct DeferredBlock {
task_id: RenderTaskId,
@ -234,14 +247,14 @@ impl<'a, T> Drop for GpuBufferWriter<'a, T> {
}
}
pub struct GpuBufferBuilder<T> {
pub struct GpuBufferBuilderImpl<T> {
data: Vec<T>,
deferred: Vec<DeferredBlock>,
}
impl<T> GpuBufferBuilder<T> where T: Texel + std::convert::From<DeviceIntRect> {
impl<T> GpuBufferBuilderImpl<T> where T: Texel + std::convert::From<DeviceIntRect> {
pub fn new() -> Self {
GpuBufferBuilder {
GpuBufferBuilderImpl {
data: Vec::new(),
deferred: Vec::new(),
}
@ -342,7 +355,7 @@ impl<T> GpuBuffer<T> {
#[test]
fn test_gpu_buffer_sizing_push() {
let render_task_graph = RenderTaskGraph::new_for_testing();
let mut builder = GpuBufferBuilder::<GpuBufferBlockF>::new();
let mut builder = GpuBufferBuilderF::new();
let row = vec![GpuBufferBlockF::EMPTY; MAX_VERTEX_TEXTURE_WIDTH];
builder.push(&row);
@ -357,7 +370,7 @@ 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::<GpuBufferBlockF>::new();
let mut builder = GpuBufferBuilderF::new();
let mut writer = builder.write_blocks(MAX_VERTEX_TEXTURE_WIDTH);
for _ in 0 .. MAX_VERTEX_TEXTURE_WIDTH {

View file

@ -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, GpuBufferF, GpuBufferBuilderF, GpuBufferI, GpuBufferBuilderI, 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

View file

@ -283,6 +283,7 @@ impl LazilyCompiledShader {
("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
("sGpuBufferF", TextureSampler::GpuBufferF),
("sGpuBufferI", TextureSampler::GpuBufferI),
],
);
}
@ -301,6 +302,7 @@ impl LazilyCompiledShader {
("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
("sClipMask", TextureSampler::ClipMask),
("sGpuBufferF", TextureSampler::GpuBufferF),
("sGpuBufferI", TextureSampler::GpuBufferI),
],
);
}

View file

@ -23,41 +23,9 @@ namespace image {
// Helpers for sending notifications to the image associated with a decoder.
///////////////////////////////////////////////////////////////////////////////
void IDecodingTask::EnsureHasEventTarget(NotNull<RasterImage*> aImage) {
if (!mEventTarget) {
// We determine the event target as late as possible, at the first dispatch
// time, because the observers bound to an imgRequest will affect it.
// We cache it rather than query for the event target each time because the
// event target can change. We don't want to risk events being executed in
// a different order than they are dispatched, which can happen if we
// selected scheduler groups which have no ordering guarantees relative to
// each other (e.g. it moves from scheduler group A for doc group DA to
// scheduler group B for doc group DB due to changing observers -- if we
// dispatched the first event on A, and the second on B, we don't know which
// will execute first.)
RefPtr<ProgressTracker> tracker = aImage->GetProgressTracker();
if (tracker) {
mEventTarget = tracker->GetEventTarget();
} else {
mEventTarget = GetMainThreadSerialEventTarget();
}
}
}
bool IDecodingTask::IsOnEventTarget() const {
// This is essentially equivalent to NS_IsOnMainThread() because all of the
// event targets are for the main thread (although perhaps with a different
// label / scheduler group). The observers in ProgressTracker may have
// different event targets from this, so this is just a best effort guess.
bool current = false;
mEventTarget->IsOnCurrentThread(&current);
return current;
}
void IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder) {
MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode());
EnsureHasEventTarget(aImage);
// Capture the decoder's state. If we need to notify asynchronously, it's
// important that we don't wait until the lambda actually runs to capture the
@ -72,7 +40,7 @@ void IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
// Synchronously notify if we can.
if (IsOnEventTarget() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
if (NS_IsMainThread() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
aImage->NotifyProgress(progress, invalidRect, frameCount, decoderFlags,
surfaceFlags);
return;
@ -86,21 +54,21 @@ void IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
// We're forced to notify asynchronously.
NotNull<RefPtr<RasterImage>> image = aImage;
mEventTarget->Dispatch(CreateRenderBlockingRunnable(NS_NewRunnableFunction(
"IDecodingTask::NotifyProgress",
[=]() -> void {
image->NotifyProgress(progress, invalidRect,
frameCount, decoderFlags,
surfaceFlags);
})),
NS_DISPATCH_NORMAL);
nsCOMPtr<nsIEventTarget> eventTarget = GetMainThreadSerialEventTarget();
eventTarget->Dispatch(CreateRenderBlockingRunnable(NS_NewRunnableFunction(
"IDecodingTask::NotifyProgress",
[=]() -> void {
image->NotifyProgress(progress, invalidRect,
frameCount, decoderFlags,
surfaceFlags);
})),
NS_DISPATCH_NORMAL);
}
void IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder) {
MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(),
"Decode complete in the middle of a frame?");
EnsureHasEventTarget(aImage);
// Capture the decoder's state.
DecoderFinalStatus finalStatus = aDecoder->FinalStatus();
@ -113,7 +81,7 @@ void IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
// Synchronously notify if we can.
if (IsOnEventTarget() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
if (NS_IsMainThread() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
aImage->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
invalidRect, frameCount, decoderFlags,
surfaceFlags);
@ -128,15 +96,16 @@ void IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
// We're forced to notify asynchronously.
NotNull<RefPtr<RasterImage>> image = aImage;
mEventTarget->Dispatch(CreateRenderBlockingRunnable(NS_NewRunnableFunction(
"IDecodingTask::NotifyDecodeComplete",
[=]() -> void {
image->NotifyDecodeComplete(
finalStatus, metadata, telemetry, progress,
invalidRect, frameCount, decoderFlags,
surfaceFlags);
})),
NS_DISPATCH_NORMAL);
nsCOMPtr<nsIEventTarget> eventTarget = GetMainThreadSerialEventTarget();
eventTarget->Dispatch(CreateRenderBlockingRunnable(NS_NewRunnableFunction(
"IDecodingTask::NotifyDecodeComplete",
[=]() -> void {
image->NotifyDecodeComplete(
finalStatus, metadata, telemetry, progress,
invalidRect, frameCount, decoderFlags,
surfaceFlags);
})),
NS_DISPATCH_NORMAL);
}
///////////////////////////////////////////////////////////////////////////////

View file

@ -53,13 +53,6 @@ class IDecodingTask : public IResumable {
/// Notify @aImage that @aDecoder has finished.
void NotifyDecodeComplete(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder);
private:
void EnsureHasEventTarget(NotNull<RasterImage*> aImage);
bool IsOnEventTarget() const;
nsCOMPtr<nsIEventTarget> mEventTarget;
};
/**

View file

@ -10,8 +10,6 @@
#include "nsISupports.h"
#include "nsRect.h"
class nsIEventTarget;
namespace mozilla {
namespace image {

View file

@ -218,7 +218,7 @@ void ImageResource::SendOnUnlockedDraw(uint32_t aFlags) {
mProgressTracker->OnUnlockedDraw();
} else {
NotNull<RefPtr<ImageResource>> image = WrapNotNull(this);
nsCOMPtr<nsIEventTarget> eventTarget = mProgressTracker->GetEventTarget();
nsCOMPtr<nsIEventTarget> eventTarget = GetMainThreadSerialEventTarget();
nsCOMPtr<nsIRunnable> ev = NS_NewRunnableFunction(
"image::ImageResource::SendOnUnlockedDraw", [=]() -> void {
RefPtr<ProgressTracker> tracker = image->GetProgressTracker();

View file

@ -408,10 +408,6 @@ void ProgressTracker::EmulateRequestFinished(IProgressObserver* aObserver) {
}
}
already_AddRefed<nsIEventTarget> ProgressTracker::GetEventTarget() const {
return do_AddRef(GetMainThreadSerialEventTarget());
}
void ProgressTracker::AddObserver(IProgressObserver* aObserver) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<IProgressObserver> observer = aObserver;

View file

@ -179,9 +179,6 @@ class ProgressTracker : public mozilla::SupportsWeakPtr {
bool RemoveObserver(IProgressObserver* aObserver);
uint32_t ObserverCount() const;
// Get the event target we should currently dispatch events to.
already_AddRefed<nsIEventTarget> GetEventTarget() const;
// Resets our weak reference to our image. Image subclasses should call this
// in their destructor.
void ResetImage();

View file

@ -480,12 +480,7 @@ void RasterImage::OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) {
bool animatedFramesDiscarded =
mAnimationState && aSurfaceKey.Playback() == PlaybackType::eAnimated;
nsCOMPtr<nsIEventTarget> eventTarget;
if (mProgressTracker) {
eventTarget = mProgressTracker->GetEventTarget();
} else {
eventTarget = do_GetMainThread();
}
nsCOMPtr<nsIEventTarget> eventTarget = do_GetMainThread();
RefPtr<RasterImage> image = this;
nsCOMPtr<nsIRunnable> ev =

View file

@ -1557,12 +1557,7 @@ void VectorImage::InvalidateObserversOnNextRefreshDriverTick() {
// set by InvalidateFrameInternal in layout/generic/nsFrame.cpp. These bits
// get cleared when we repaint the SVG into a surface by
// nsIFrame::ClearInvalidationStateBits in nsDisplayList::PaintRoot.
nsCOMPtr<nsIEventTarget> eventTarget;
if (mProgressTracker) {
eventTarget = mProgressTracker->GetEventTarget();
} else {
eventTarget = do_GetMainThread();
}
nsCOMPtr<nsIEventTarget> eventTarget = do_GetMainThread();
RefPtr<VectorImage> self(this);
nsCOMPtr<nsIRunnable> ev(NS_NewRunnableFunction(

View file

@ -334,8 +334,7 @@ void imgRequest::Cancel(nsresult aStatus) {
if (NS_IsMainThread()) {
ContinueCancel(aStatus);
} else {
RefPtr<ProgressTracker> progressTracker = GetProgressTracker();
nsCOMPtr<nsIEventTarget> eventTarget = progressTracker->GetEventTarget();
nsCOMPtr<nsIEventTarget> eventTarget = GetMainThreadSerialEventTarget();
nsCOMPtr<nsIRunnable> ev = new imgRequestMainThreadCancel(this, aStatus);
eventTarget->Dispatch(ev.forget(), NS_DISPATCH_NORMAL);
}
@ -1027,26 +1026,23 @@ imgRequest::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInStr,
if (result.mImage) {
image = result.mImage;
nsCOMPtr<nsIEventTarget> eventTarget;
// Update our state to reflect this new part.
{
MutexAutoLock lock(mMutex);
mImage = image;
// We only get an event target if we are not on the main thread, because
// we have to dispatch in that case. If we are on the main thread, but
// on a different scheduler group than ProgressTracker would give us,
// that is okay because nothing in imagelib requires that, just our
// listeners (which have their own checks).
if (!NS_IsMainThread()) {
eventTarget = mProgressTracker->GetEventTarget();
MOZ_ASSERT(eventTarget);
}
mProgressTracker = nullptr;
}
// We only get an event target if we are not on the main thread, because
// we have to dispatch in that case.
nsCOMPtr<nsIEventTarget> eventTarget;
if (!NS_IsMainThread()) {
eventTarget = GetMainThreadSerialEventTarget();
MOZ_ASSERT(eventTarget);
}
// Some property objects are not threadsafe, and we need to send
// OnImageAvailable on the main thread, so finish on the main thread.
if (!eventTarget) {

View file

@ -2213,7 +2213,7 @@ def listIANAFiles(tzdataDir):
def readIANAFiles(tzdataDir, files):
"""Read all IANA time zone files from the given iterable."""
nameSyntax = "[\w/+\-]+"
nameSyntax = r"[\w/+\-]+"
pZone = re.compile(r"Zone\s+(?P<name>%s)\s+.*" % nameSyntax)
pLink = re.compile(
r"Link\s+(?P<target>%s)\s+(?P<name>%s)(?:\s+#.*)?" % (nameSyntax, nameSyntax)
@ -2310,7 +2310,7 @@ def readICUResourceFile(filename):
maybeMultiComments = r"(?:/\*[^*]*\*/)*"
maybeSingleComment = r"(?://.*)?"
lineStart = "^%s" % maybeMultiComments
lineEnd = "%s\s*%s$" % (maybeMultiComments, maybeSingleComment)
lineEnd = r"%s\s*%s$" % (maybeMultiComments, maybeSingleComment)
return re.compile(r"\s*".join(chain([lineStart], args, [lineEnd])))
tableName = r'(?P<quote>"?)(?P<name>.+?)(?P=quote)'
@ -2554,7 +2554,7 @@ def icuTzDataVersion(icuTzDir):
zoneinfo = os.path.join(icuTzDir, "zoneinfo64.txt")
if not os.path.isfile(zoneinfo):
raise RuntimeError("file not found: %s" % zoneinfo)
version = searchInFile("^//\s+tz version:\s+([0-9]{4}[a-z])$", zoneinfo)
version = searchInFile(r"^//\s+tz version:\s+([0-9]{4}[a-z])$", zoneinfo)
if version is None:
raise RuntimeError(
"%s does not contain a valid tzdata version string" % zoneinfo
@ -3711,7 +3711,7 @@ const allUnits = {};
""".format(
all_units_array
)
+ """
+ r"""
// Test only sanctioned unit identifiers are allowed.
for (const typeAndUnit of allUnits) {

View file

@ -22,7 +22,7 @@ ALIGNMENT_COLUMN = 20
# The maximum column for comment
MAX_CHARS_PER_LINE = 80
stack_comment_pat = re.compile("^( *//) *(\[stack\].*)$")
stack_comment_pat = re.compile(r"^( *//) *(\[stack\].*)$")
def align_stack_comment(path):

View file

@ -271,7 +271,7 @@ def implemented_types(t):
yield t2
template_regexp = re.compile("([\w_:]+)<")
template_regexp = re.compile(r"([\w_:]+)<")
def is_struct_or_union(t):

View file

@ -40,9 +40,9 @@ def _relpath(path, start=None):
os.path.relpath = _relpath
# Characters that need to be escaped when used in shell words.
shell_need_escapes = re.compile("[^\w\d%+,-./:=@'\"]", re.DOTALL)
shell_need_escapes = re.compile("[^\\w\\d%+,-./:=@'\"]", re.DOTALL)
# Characters that need to be escaped within double-quoted strings.
shell_dquote_escapes = re.compile('[^\w\d%+,-./:=@"]', re.DOTALL)
shell_dquote_escapes = re.compile('[^\\w\\d%+,-./:=@"]', re.DOTALL)
def make_shell_cmd(l):

View file

@ -13,10 +13,10 @@ run_fragment("ExecutableAllocator.onepool")
reExecPool = "ExecutablePool [a-f0-9]{8,}-[a-f0-9]{8,}"
assert_regexp_pretty("pool", reExecPool)
assert_regexp_pretty("execAlloc", "ExecutableAllocator\(\[" + reExecPool + "\]\)")
assert_regexp_pretty("execAlloc", r"ExecutableAllocator\(\[" + reExecPool + r"\]\)")
run_fragment("ExecutableAllocator.twopools")
assert_regexp_pretty(
"execAlloc", "ExecutableAllocator\(\[" + reExecPool + ", " + reExecPool + "\]\)"
"execAlloc", r"ExecutableAllocator\(\[" + reExecPool + ", " + reExecPool + r"\]\)"
)

View file

@ -40,25 +40,33 @@ for (let i of [
)`, /(type mismatch|table with non-nullable references requires initializer)/);
}
var t1 = new WebAssembly.Table({initial: 10, element: {ref: 'func', nullable: false }}, sampleWasmFunction);
let values = "10 funcref (ref.func $dummy)";
let t1 = new wasmEvalText(`(module (func $dummy) (table (export "t1") ${values}))`).exports.t1;
assertEq(t1.get(2) != null, true);
assertThrows(() => {
new WebAssembly.Table({initial: 10, element: {ref: 'func', nullable: false }});
});
assertThrows(() => {
new WebAssembly.Table({initial: 10, element: {ref: 'func', nullable: false }}, null);
});
var t2 = new WebAssembly.Table({initial: 6, maximum: 20, element: {ref: 'extern', nullable: false }}, {foo: "bar"});
assertEq(t2.get(1).foo, "bar");
wasmFailValidateText(`(module
(table $t 10 (ref func))
)`, /table with non-nullable references requires initializer/);
wasmFailValidateText(`
(module
(func $dummy)
(table (export "t") 10 funcref (ref.null none))
)`, /type mismatch/);
const foo = "bar";
const { t2, get } = wasmEvalText(`
(module
(global (import "" "foo") externref)
(table (export "t2") 6 20 externref (global.get 0))
)`, { "": { "foo": foo } }).exports;
assertEq(t2.get(5), "bar");
assertThrows(() => { t2.get(7) });
assertThrows(() => { t2.grow(9, null) });
assertThrows(() => { t2.grow(30, null) });
t2.grow(8, {t: "test"});
assertEq(t2.get(3).foo, "bar");
assertEq(t2.get(3), "bar");
assertEq(t2.get(7).t, "test");
assertThrows(() => {
new WebAssembly.Table({initial: 10, element: {ref: 'extern', nullable: false }}, null);
});
// Fail because tables come before globals in the binary format, so tables
// cannot refer to globals.

View file

@ -16,36 +16,6 @@ assertErrorMessage(
assertErrorMessage(
() => new WebAssembly.Table({element: true, initial: 1}),
TypeError, /bad value type/);
// RefType/ValueType can be specified as an {ref: 'func', ...} object
const t11 = new WebAssembly.Table({element: {ref: 'func', nullable: true}, initial: 3});
const t12 = new WebAssembly.Table({element: {ref: 'extern', nullable: true}, initial: 3});
const t13 = new WebAssembly.Table({element: {ref: 'extern', nullable: false}, initial: 3}, {});
assertErrorMessage(
() => new WebAssembly.Table({element: {ref: 'func', nullable: false}, initial: 1}, null),
TypeError, /cannot pass null to non-nullable WebAssembly reference/);
assertErrorMessage(
() => new WebAssembly.Table({element: {ref: 'extern', nullable: false}, initial: 1}, null),
TypeError, /cannot pass null to non-nullable WebAssembly reference/);
assertErrorMessage(
() => new WebAssembly.Table({element: {ref: 'bar', nullable: true}, initial: 1}),
TypeError, /bad value type/);
const g11 = new WebAssembly.Global({value: {ref: 'func', nullable: true}, mutable: true});
const g12 = new WebAssembly.Global({value: {ref: 'extern', nullable: true}, mutable: true});
const g13 = new WebAssembly.Global({value: {ref: 'extern', nullable: false}, mutable: true}, {});
const g14 = new WebAssembly.Global({value: {ref: 'extern', nullable: false}, mutable: true});
const g15 = new WebAssembly.Global({value: {ref: 'extern', nullable: false}, mutable: true}, void 0);
assertErrorMessage(
() => new WebAssembly.Global({value: {ref: 'func', nullable: false}, mutable: true}),
TypeError, /cannot pass null to non-nullable WebAssembly reference/);
assertErrorMessage(
() => new WebAssembly.Global({value: {ref: 'extern', nullable: false}, mutable: true}, null),
TypeError, /cannot pass null to non-nullable WebAssembly reference/);
assertErrorMessage(
() => new WebAssembly.Global({value: {ref: 'bar', nullable: true}, mutable: true}),
TypeError, /bad value type/);

View file

@ -160,7 +160,7 @@ do_test()
#
# The timeout command send a SIGTERM signal, which should return 143
# (=128+15). However, due to a bug in tinybox, it returns 142.
if test \( $rc -eq 143 -o $rc -eq 142 \) -a $attempt -lt {retry}; then
if test \\( $rc -eq 143 -o $rc -eq 142 \\) -a $attempt -lt {retry}; then
echo '\\n{tag}RETRY='$rc,$time
attempt=$((attempt + 1))
do_test $idx $attempt "$@"

View file

@ -18,7 +18,7 @@ def to_code_list(codes):
def convert(dir):
ver_pat = re.compile("NormalizationTest-([0-9\.]+)\.txt")
ver_pat = re.compile(r"NormalizationTest-([0-9\.]+)\.txt")
part_pat = re.compile("^@(Part([0-9]+) .+)$")
test_pat = re.compile(
"^([0-9A-Fa-f ]+);([0-9A-Fa-f ]+);([0-9A-Fa-f ]+);([0-9A-Fa-f ]+);([0-9A-Fa-f ]+);$"

View file

@ -237,7 +237,7 @@ def mergeMeta(reftest, frontmatter, includes):
if info:
# Open some space in an existing info text
if "info" in frontmatter:
frontmatter["info"] += "\n\n \%s" % info
frontmatter["info"] += "\n\n \\%s" % info
else:
frontmatter["info"] = info

View file

@ -1111,7 +1111,7 @@ def make_regexp_space_test(version, test_space_table, codepoint_table):
test_space.write(",\n".join(map(hex_and_name, test_space_table)))
test_space.write("\n);\n")
test_space.write(
"""
r"""
assertEq(/^\s+$/.exec(onlySpace) !== null, true);
assertEq(/^[\s]+$/.exec(onlySpace) !== null, true);
assertEq(/^[^\s]+$/.exec(onlySpace) === null, true);

View file

@ -150,94 +150,7 @@ enum class RefTypeResult {
Unparsed,
};
static RefTypeResult MaybeToRefType(JSContext* cx, HandleObject obj,
RefType* out) {
#ifdef ENABLE_WASM_FUNCTION_REFERENCES
if (!wasm::FunctionReferencesAvailable(cx)) {
return RefTypeResult::Unparsed;
}
JSAtom* refAtom = Atomize(cx, "ref", strlen("ref"));
if (!refAtom) {
return RefTypeResult::Failure;
}
RootedId refId(cx, AtomToId(refAtom));
RootedValue refVal(cx);
if (!GetProperty(cx, obj, obj, refId, &refVal)) {
return RefTypeResult::Failure;
}
RootedString typeStr(cx, ToString(cx, refVal));
if (!typeStr) {
return RefTypeResult::Failure;
}
Rooted<JSLinearString*> typeLinearStr(cx, typeStr->ensureLinear(cx));
if (!typeLinearStr) {
return RefTypeResult::Failure;
}
if (StringEqualsLiteral(typeLinearStr, "func")) {
*out = RefType::func();
} else if (StringEqualsLiteral(typeLinearStr, "extern")) {
*out = RefType::extern_();
# ifdef ENABLE_WASM_EXNREF
} else if (ExnRefAvailable(cx) && StringEqualsLiteral(typeLinearStr, "exn")) {
*out = RefType::exn();
# endif
# ifdef ENABLE_WASM_GC
} else if (GcAvailable(cx) && StringEqualsLiteral(typeLinearStr, "any")) {
*out = RefType::any();
} else if (GcAvailable(cx) && StringEqualsLiteral(typeLinearStr, "eq")) {
*out = RefType::eq();
} else if (GcAvailable(cx) && StringEqualsLiteral(typeLinearStr, "i31")) {
*out = RefType::i31();
} else if (GcAvailable(cx) && StringEqualsLiteral(typeLinearStr, "struct")) {
*out = RefType::struct_();
} else if (GcAvailable(cx) && StringEqualsLiteral(typeLinearStr, "array")) {
*out = RefType::array();
# endif
} else {
return RefTypeResult::Unparsed;
}
JSAtom* nullableAtom = Atomize(cx, "nullable", strlen("nullable"));
if (!nullableAtom) {
return RefTypeResult::Failure;
}
RootedId nullableId(cx, AtomToId(nullableAtom));
RootedValue nullableVal(cx);
if (!GetProperty(cx, obj, obj, nullableId, &nullableVal)) {
return RefTypeResult::Failure;
}
bool nullable = ToBoolean(nullableVal);
if (!nullable) {
*out = out->asNonNullable();
}
MOZ_ASSERT(out->isNullable() == nullable);
return RefTypeResult::Parsed;
#else
return RefTypeResult::Unparsed;
#endif
}
bool wasm::ToValType(JSContext* cx, HandleValue v, ValType* out) {
if (v.isObject()) {
RootedObject obj(cx, &v.toObject());
RefType refType;
switch (MaybeToRefType(cx, obj, &refType)) {
case RefTypeResult::Failure:
return false;
case RefTypeResult::Parsed:
*out = ValType(refType);
return true;
case RefTypeResult::Unparsed:
break;
}
}
RootedString typeStr(cx, ToString(cx, v));
if (!typeStr) {
return false;
@ -274,18 +187,6 @@ bool wasm::ToValType(JSContext* cx, HandleValue v, ValType* out) {
}
bool wasm::ToRefType(JSContext* cx, HandleValue v, RefType* out) {
if (v.isObject()) {
RootedObject obj(cx, &v.toObject());
switch (MaybeToRefType(cx, obj, out)) {
case RefTypeResult::Failure:
return false;
case RefTypeResult::Parsed:
return true;
case RefTypeResult::Unparsed:
break;
}
}
RootedString typeStr(cx, ToString(cx, v));
if (!typeStr) {
return false;

View file

@ -800,7 +800,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
checkThrows(function() { trickyObject.hasOwnProperty = 33; }, /shadow/,
"Should reject shadowing of pre-existing inherited properties over Xrays");
checkThrows(function() { Object.defineProperty(trickyObject, 'rejectedProp', { get() {}}); },
checkThrows(function() { Object.defineProperty(trickyObject, 'rejectedProp', { get() { return undefined; }}); },
/accessor property/, "Should reject accessor property definition");
}

View file

@ -64,22 +64,29 @@ nsresult nsNumberControlFrame::CreateAnonymousContent(
nsTextControlFrame::CreateAnonymousContent(aElements);
#if defined(MOZ_WIDGET_ANDROID)
// We don't want spin buttons on Android
return NS_OK;
#else
// The author has elected to hide the spinner by setting this
// -moz-appearance. We will reframe if it changes.
if (StyleDisplay()->EffectiveAppearance() != StyleAppearance::Textfield) {
// Create the ::-moz-number-spin-box pseudo-element:
mSpinBox = MakeAnonElement(PseudoStyleType::mozNumberSpinBox);
// Create the ::-moz-number-spin-up pseudo-element:
mSpinUp = MakeAnonElement(PseudoStyleType::mozNumberSpinUp, mSpinBox);
// Create the ::-moz-number-spin-down pseudo-element:
mSpinDown = MakeAnonElement(PseudoStyleType::mozNumberSpinDown, mSpinBox);
aElements.AppendElement(mSpinBox);
if (StyleDisplay()->EffectiveAppearance() == StyleAppearance::Textfield) {
return NS_OK;
}
// Create the ::-moz-number-spin-box pseudo-element:
mSpinBox = MakeAnonElement(PseudoStyleType::mozNumberSpinBox);
// Create the ::-moz-number-spin-up pseudo-element:
mSpinUp = MakeAnonElement(PseudoStyleType::mozNumberSpinUp, mSpinBox);
// Create the ::-moz-number-spin-down pseudo-element:
mSpinDown = MakeAnonElement(PseudoStyleType::mozNumberSpinDown, mSpinBox);
aElements.AppendElement(mSpinBox);
return NS_OK;
#endif
}
/* static */

View file

@ -5413,7 +5413,15 @@ static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame,
const nsPoint& aPoint,
uint32_t aFlags);
static bool SelfIsSelectable(nsIFrame* aFrame, uint32_t aFlags) {
static bool SelfIsSelectable(nsIFrame* aFrame, nsIFrame* aParentFrame,
uint32_t aFlags) {
// We should not move selection into a native anonymous subtree when handling
// selection outside it.
if ((aFlags & nsIFrame::IGNORE_NATIVE_ANONYMOUS_SUBTREE) &&
aParentFrame->GetClosestNativeAnonymousSubtreeRoot() !=
aFrame->GetClosestNativeAnonymousSubtreeRoot()) {
return false;
}
if ((aFlags & nsIFrame::SKIP_HIDDEN) &&
!aFrame->StyleVisibility()->IsVisible()) {
return false;
@ -5476,21 +5484,28 @@ static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame, bool aEndFrame,
nsIFrame* result = nullptr;
nsIFrame* frame = aFrame->PrincipalChildList().FirstChild();
if (!aEndFrame) {
while (frame && (!SelfIsSelectable(frame, aFlags) || frame->IsEmpty()))
while (frame &&
(!SelfIsSelectable(frame, aFrame, aFlags) || frame->IsEmpty())) {
frame = frame->GetNextSibling();
if (frame) result = frame;
}
if (frame) {
result = frame;
}
} else {
// Because the frame tree is singly linked, to find the last frame,
// we have to iterate through all the frames
// XXX I have a feeling this could be slow for long blocks, although
// I can't find any slowdowns
while (frame) {
if (!frame->IsEmpty() && SelfIsSelectable(frame, aFlags))
if (!frame->IsEmpty() && SelfIsSelectable(frame, aFrame, aFlags)) {
result = frame;
}
frame = frame->GetNextSibling();
}
}
if (result) return DrillDownToSelectionFrame(result, aEndFrame, aFlags);
if (result) {
return DrillDownToSelectionFrame(result, aEndFrame, aFlags);
}
}
// If the current frame has no targetable children, target the current frame
return FrameTarget{aFrame, true, aEndFrame};
@ -5502,8 +5517,9 @@ static FrameTarget GetSelectionClosestFrameForLine(
nsBlockFrame* aParent, nsBlockFrame::LineIterator aLine,
const nsPoint& aPoint, uint32_t aFlags) {
// Account for end of lines (any iterator from the block is valid)
if (aLine == aParent->LinesEnd())
if (aLine == aParent->LinesEnd()) {
return DrillDownToSelectionFrame(aParent, true, aFlags);
}
nsIFrame* frame = aLine->mFirstChild;
nsIFrame* closestFromIStart = nullptr;
nsIFrame* closestFromIEnd = nullptr;
@ -5519,7 +5535,7 @@ static FrameTarget GetSelectionClosestFrameForLine(
// the previous thing had a different editableness than us, since then we
// may end up not being able to select after it if the br is the last thing
// on the line.
if (!SelfIsSelectable(frame, aFlags) || frame->IsEmpty() ||
if (!SelfIsSelectable(frame, aParent, aFlags) || frame->IsEmpty() ||
(canSkipBr && frame->IsBrFrame() &&
lastFrameWasEditable == frame->GetContent()->IsEditable())) {
continue;
@ -5699,7 +5715,7 @@ static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame,
// Go through all the child frames to find the closest one
nsIFrame::FrameWithDistance closest = {nullptr, nscoord_MAX, nscoord_MAX};
for (; kid; kid = kid->GetNextSibling()) {
if (!SelfIsSelectable(kid, aFlags) || kid->IsEmpty()) {
if (!SelfIsSelectable(kid, aFrame, aFlags) || kid->IsEmpty()) {
continue;
}
@ -9391,7 +9407,8 @@ nsresult nsIFrame::PeekOffsetForLineEdge(PeekOffsetStruct* aPos) {
}
}
}
FrameTarget targetFrame = DrillDownToSelectionFrame(baseFrame, endOfLine, 0);
FrameTarget targetFrame = DrillDownToSelectionFrame(
baseFrame, endOfLine, nsIFrame::IGNORE_NATIVE_ANONYMOUS_SUBTREE);
SetPeekResultFromFrame(*aPos, targetFrame.frame, endOfLine ? -1 : 0,
OffsetIsAtLineEdge::Yes);
if (endOfLine && targetFrame.frame->HasSignificantTerminalNewline()) {

View file

@ -0,0 +1,2 @@
<!doctype html>
<input type=number>

View file

@ -1,5 +1,5 @@
# sanity checks:
!= not-other-type-unthemed-1.html not-other-type-unthemed-1a-notref.html
fails-if(Android) pref(dom.forms.number.hide_spin_buttons_when_no_hover_or_focus,false) != not-other-type-unthemed-1.html not-other-type-unthemed-1a-notref.html
!= not-other-type-unthemed-1.html not-other-type-unthemed-1b-notref.html
# should look the same as type=text, except for the spin box
@ -17,7 +17,7 @@ fuzzy(0-2,0-13) == show-value.html show-value-ref.html
# disabled
== number-disabled.html number-disabled-ref.html
!= number-spinbox-disabled.html number-spinbox-disabled-notref.html
fails-if(Android) pref(dom.forms.number.hide_spin_buttons_when_no_hover_or_focus,false) != number-spinbox-disabled.html number-spinbox-disabled-notref.html
# auto width:
== number-auto-width-1.html number-auto-width-1-ref.html
@ -72,3 +72,5 @@ fuzzy(0-14,0-4) == clipped-text.html clipped-text-ref.html
fails-if(useDrawSnapshot) needs-focus != caret-right.html caret-right-notref.html
fails-if(useDrawSnapshot) needs-focus != caret-left-rtl.html caret-left-rtl-notref.html
fails-if(useDrawSnapshot) needs-focus != caret-right-vertical.html caret-right-vertical-notref.html
fails-if(Android) test-pref(dom.forms.number.hide_spin_buttons_when_no_hover_or_focus,true) ref-pref(dom.forms.number.hide_spin_buttons_when_no_hover_or_focus,false) != number.html number.html

View file

@ -868,6 +868,13 @@ input[type=number]::-moz-number-spin-box {
overflow: clip;
}
/* stylelint-disable-next-line media-query-no-invalid */
@media (-moz-bool-pref: "dom.forms.number.hide_spin_buttons_when_no_hover_or_focus") {
input[type=number]:not(:hover, :focus)::-moz-number-spin-box {
opacity: 0;
}
}
input[type=number]::-moz-number-spin-up,
input[type=number]::-moz-number-spin-down {
writing-mode: horizontal-tb;

View file

@ -252,7 +252,7 @@ class ReftestResolver(object):
rv = [
(
os.path.join(dirname, default_manifest),
r".*%s(?:[#?].*)?$" % pathname.replace("?", "\?"),
r".*%s(?:[#?].*)?$" % pathname.replace("?", r"\?"),
)
]

View file

@ -83,7 +83,7 @@ def substs(variables, values):
# Safe substitute leaves unrecognized variables in place.
# We replace them with the empty string.
new_values.append(re.sub('\$\{\w+\}', '', new_value))
new_values.append(re.sub(r'\$\{\w+\}', '', new_value))
return new_values
@ -240,7 +240,7 @@ def evaluate_boolean(variables, arguments):
# If statements can have old-style variables which are not demarcated
# like ${VARIABLE}. Attempt to look up the variable both ways.
try:
if re.search('\$\{\w+\}', argument):
if re.search(r'\$\{\w+\}', argument):
try:
t = Template(argument)
value = t.substitute(variables)

View file

@ -2351,7 +2351,7 @@
# see https://html.spec.whatwg.org/#the-popover-attribute
- name: dom.element.popover.enabled
type: RelaxedAtomicBool
value: @IS_NIGHTLY_BUILD@
value: true
mirror: always
rust: true
@ -2635,6 +2635,13 @@
value: false
mirror: always
# Whether the spin buttons will always appear, or if they
# will only appear when the input is focused or hovered.
- name: dom.forms.number.hide_spin_buttons_when_no_hover_or_focus
type: bool
value: @IS_NIGHTLY_BUILD@
mirror: always
# Whether the Gamepad API is enabled
- name: dom.gamepad.enabled
type: bool

View file

@ -579,6 +579,8 @@ nsresult ResolveHTTPSRecordImpl(const nsACString& aHost, uint16_t aFlags,
return NS_ERROR_NOT_IMPLEMENTED;
}
void DNSThreadShutdown() {}
#endif // MOZ_NO_HTTPS_IMPL
} // namespace mozilla::net

View file

@ -527,6 +527,10 @@ nsresult Http3WebTransportStream::WriteSegments() {
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
rv = NS_OK;
}
if (rv == NS_BASE_STREAM_CLOSED) {
mReceiveStreamPipeOut->Close();
rv = NS_OK;
}
again = false;
} else if (NS_FAILED(mSocketInCondition)) {
if (mSocketInCondition != NS_BASE_STREAM_WOULD_BLOCK) {

View file

@ -3090,30 +3090,19 @@ HttpChannelChild::GetDeliveryTarget(nsISerialEventTarget** aEventTarget) {
void HttpChannelChild::TrySendDeletingChannel() {
AUTO_PROFILER_LABEL("HttpChannelChild::TrySendDeletingChannel", NETWORK);
MOZ_ASSERT(NS_IsMainThread());
if (!mDeletingChannelSent.compareExchange(false, true)) {
// SendDeletingChannel is already sent.
return;
}
if (NS_IsMainThread()) {
if (NS_WARN_IF(!CanSend())) {
// IPC actor is destroyed already, do not send more messages.
return;
}
Unused << PHttpChannelChild::SendDeletingChannel();
if (NS_WARN_IF(!CanSend())) {
// IPC actor is destroyed already, do not send more messages.
return;
}
nsCOMPtr<nsISerialEventTarget> neckoTarget = GetNeckoTarget();
MOZ_ASSERT(neckoTarget);
DebugOnly<nsresult> rv = neckoTarget->Dispatch(
NewNonOwningRunnableMethod(
"net::HttpChannelChild::TrySendDeletingChannel", this,
&HttpChannelChild::TrySendDeletingChannel),
NS_DISPATCH_NORMAL);
MOZ_ASSERT(NS_SUCCEEDED(rv));
Unused << PHttpChannelChild::SendDeletingChannel();
}
nsresult HttpChannelChild::AsyncCallImpl(

View file

@ -6963,7 +6963,7 @@ nsHttpChannel::OnProxyAvailable(nsICancelable* request, nsIChannel* channel,
mProxyInfo->GetType(type);
uint32_t flags = 0;
mProxyInfo->GetFlags(&flags);
printf("type=%s, flags=%i\n", type.get(), flags);
if (type.EqualsLiteral("socks")) {
if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
glean::networking::proxy_info_type

View file

@ -525,3 +525,27 @@ function makeHTTPChannel(url, with_proxy) {
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
}
// Like ChannelListener but does not throw an exception if something
// goes wrong. Callback is supposed to do all the work.
class SimpleChannelListener {
constructor(callback) {
this._onStopCallback = callback;
this._buffer = "";
}
get QueryInterface() {
return ChromeUtils.generateQI(["nsIStreamListener", "nsIRequestObserver"]);
}
onStartRequest(request) {}
onDataAvailable(request, stream, offset, count) {
this._buffer = this._buffer.concat(read_stream(stream, count));
}
onStopRequest(request, status) {
if (this._onStopCallback) {
this._onStopCallback(request, this._buffer);
}
}
}

View file

@ -18,32 +18,41 @@ var httpbody = "0123456789";
var live_channels = [];
function run_test() {
add_task(async function test() {
httpserver.registerPathHandler(testpath, serverHandler);
httpserver.start(-1);
registerCleanupFunction(async () => {
if (httpserver) {
await httpserver.stop();
}
});
httpProtocolHandler.EnsureHSTSDataReady().then(function () {
var local_channel;
await httpProtocolHandler.EnsureHSTSDataReady();
// Opened channel that has no remaining references on shutdown
local_channel = setupChannel(testpath);
local_channel.asyncOpen(new ChannelListener(checkRequest, local_channel));
// Opened channel that has no remaining references on shutdown
let local_channel = setupChannel(testpath);
local_channel.asyncOpen(new SimpleChannelListener());
// Opened channel that has no remaining references after being opened
setupChannel(testpath).asyncOpen(new ChannelListener(function () {}, null));
// Opened channel that has no remaining references after being opened
setupChannel(testpath).asyncOpen(new SimpleChannelListener());
// Unopened channel that has remaining references on shutdown
live_channels.push(setupChannel(testpath));
// Unopened channel that has remaining references on shutdown
live_channels.push(setupChannel(testpath));
// Opened channel that has remaining references on shutdown
live_channels.push(setupChannel(testpath));
// Opened channel that has remaining references on shutdown
live_channels.push(setupChannel(testpath));
await new Promise(resolve => {
live_channels[1].asyncOpen(
new ChannelListener(checkRequestFinish, live_channels[1])
new SimpleChannelListener((req, data) => {
Assert.equal(data, httpbody);
resolve();
})
);
});
do_test_pending();
}
await httpserver.stop();
httpserver = null;
});
function setupChannel(path) {
var chan = NetUtil.newChannel({
@ -59,12 +68,3 @@ function serverHandler(metadata, response) {
response.setHeader("Content-Type", "text/plain", false);
response.bodyOutputStream.write(httpbody, httpbody.length);
}
function checkRequest(request, data, context) {
Assert.equal(data, httpbody);
}
function checkRequestFinish(request, data, context) {
checkRequest(request, data, context);
httpserver.stop(do_test_finished);
}

View file

@ -434,7 +434,6 @@ run-sequentially = "node server exceptions dont replay well"
run-sequentially = "node server exceptions dont replay well"
["test_channel_close.js"]
skip-if = ["socketprocess_networking"]
["test_channel_long_domain.js"]

View file

@ -46,13 +46,13 @@ def toggle_beta_status(is_beta):
check_files_exist()
if (is_beta):
print("adding Beta status to version numbers")
sed_inplace('s/^\(#define *PR_VERSION *\"[0-9.]\+\)\" *$/\\1 Beta\"/', prinit_h)
sed_inplace('s/^\(#define *PR_BETA *\)PR_FALSE *$/\\1PR_TRUE/', prinit_h)
sed_inplace('s/^\\(#define *PR_VERSION *\"[0-9.]\\+\\)\" *$/\\1 Beta\"/', prinit_h)
sed_inplace('s/^\\(#define *PR_BETA *\\)PR_FALSE *$/\\1PR_TRUE/', prinit_h)
else:
print("removing Beta status from version numbers")
sed_inplace('s/^\(#define *PR_VERSION *\"[0-9.]\+\) *Beta\" *$/\\1\"/', prinit_h)
sed_inplace('s/^\(#define *PR_BETA *\)PR_TRUE *$/\\1PR_FALSE/', prinit_h)
sed_inplace('s/^\\(#define *PR_VERSION *\"[0-9.]\\+\\) *Beta\" *$/\\1\"/', prinit_h)
sed_inplace('s/^\\(#define *PR_BETA *\\)PR_TRUE *$/\\1PR_FALSE/', prinit_h)
print("please run 'hg stat' and 'hg diff' to verify the files have been verified correctly")
def print_beta_versions():
@ -81,22 +81,22 @@ def ensure_arguments_after_action(how_many, usage):
exit_with_failure("incorrect number of arguments, expected parameters are:\n" + usage)
def set_major_versions(major):
sed_inplace('s/^\(#define *PR_VMAJOR *\).*$/\\1' + major + '/', prinit_h)
sed_inplace('s/^\\(#define *PR_VMAJOR *\\).*$/\\1' + major + '/', prinit_h)
sed_inplace('s/^MOD_MAJOR_VERSION=.*$/MOD_MAJOR_VERSION=' + major + '/', f_conf)
sed_inplace('s/^MOD_MAJOR_VERSION=.*$/MOD_MAJOR_VERSION=' + major + '/', f_conf_in)
def set_minor_versions(minor):
sed_inplace('s/^\(#define *PR_VMINOR *\).*$/\\1' + minor + '/', prinit_h)
sed_inplace('s/^\\(#define *PR_VMINOR *\\).*$/\\1' + minor + '/', prinit_h)
sed_inplace('s/^MOD_MINOR_VERSION=.*$/MOD_MINOR_VERSION=' + minor + '/', f_conf)
sed_inplace('s/^MOD_MINOR_VERSION=.*$/MOD_MINOR_VERSION=' + minor + '/', f_conf_in)
def set_patch_versions(patch):
sed_inplace('s/^\(#define *PR_VPATCH *\).*$/\\1' + patch + '/', prinit_h)
sed_inplace('s/^\\(#define *PR_VPATCH *\\).*$/\\1' + patch + '/', prinit_h)
sed_inplace('s/^MOD_PATCH_VERSION=.*$/MOD_PATCH_VERSION=' + patch + '/', f_conf)
sed_inplace('s/^MOD_PATCH_VERSION=.*$/MOD_PATCH_VERSION=' + patch + '/', f_conf_in)
def set_full_lib_versions(version):
sed_inplace('s/^\(#define *PR_VERSION *\"\)\([0-9.]\+\)\(.*\)$/\\1' + version + '\\3/', prinit_h)
sed_inplace('s/^\\(#define *PR_VERSION *\"\\)\\([0-9.]\\+\\)\\(.*\\)$/\\1' + version + '\\3/', prinit_h)
def set_all_lib_versions(version, major, minor, patch):
set_full_lib_versions(version)

View file

@ -10,7 +10,7 @@ class STRIP_LABEL(TransformPattern):
# Used to remove `<label data-l10n-name="remove-search-engine-article">` from a string
def visit_TextElement(self, node):
node.value = re.sub(
'\s?<label data-l10n-name="remove-search-engine-article">.+?</label>\s?',
r'\s?<label data-l10n-name="remove-search-engine-article">.+?</label>\s?',
"",
node.value,
)

View file

@ -375,7 +375,7 @@ def parse_chrome_manifest(path, base_path, chrome_entries):
###
def get_version_maybe_buildid(app_version):
def _extract_numeric_part(part):
matches = re.compile("[^\d]").search(part)
matches = re.compile(r"[^\d]").search(part)
if matches:
part = part[0 : matches.start()]
if len(part) == 0:

Some files were not shown because too many files have changed in this diff Show more