SkVM implements switches as a pseudo-loop; breaks are handled with the
condition mask just like a for loop. Fallthrough is handled via a
scratch Value in a temporary slot. `writeStore` neeeded to be refactored
to support writing into slot(s) without an associated Variable.
At IR generation time, SwitchStatements are now emitted without error
even in strict-ES2 mode. The GLSL code generator currently reports these
as an error in strict-ES2 mode, but this will be fixed in a followup
coming shortly (the switch will be rewritten as ifs inside a one-shot
loop, similar to our IR-rewrite strategy).
Change-Id: I5507257246c42a35d2f46b4b9a89492a5ffeff9b
Bug: skia:12450
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451421
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Remove drawing from the bench's constructor. This allows easier
debugging and measurement of RasterPipeline.
Change-Id: Iec974eef171917e849130fc68361e80ec1642100
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452357
Commit-Queue: Herb Derby <herb@google.com>
Auto-Submit: Herb Derby <herb@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
Change-Id: Idc09f052864601498d28c3cfe17b12ef09977543
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452318
Auto-Submit: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Change-Id: I051b6c7237ad95fde372542e123d58929d485248
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452316
Commit-Queue: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Auto-Submit: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This is a reland of 0541a983ef
This time with Generic_Error.png instead of Generic Error.png, because
the space caused problems.
Original change's description:
> bench: Add PhoneHub assets to skottie-vs-png decode bench
>
> The skottie-vs-png decode bench is intended to facilitate comparison
> between Lottie and PNG, but such a comparison cannot really be made when
> the Lottie files are unrelated to the PNG files (Lottie files chosen to
> represent a range of vector graphic complexity, versus PNG files chosen
> to represent a range of image dimensions). This CL adds PhoneHub assets
> in PNG and Lottie, including various Lottie files created using
> different optimization strategies (see added code comments for details).
>
> Change-Id: I1a4357ab0af22b9db7b7ce83fd07d48c77db7680
> Bug: chromium:1128684
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/442476
> Reviewed-by: Avery Musbach <amusbach@google.com>
> Reviewed-by: Florin Malita <fmalita@google.com>
> Commit-Queue: Florin Malita <fmalita@google.com>
Bug: chromium:1128684
Change-Id: I1a5e21f67f52b03fa1c06192ef7190f41b04e3dc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452300
Reviewed-by: Florin Malita <fmalita@google.com>
Commit-Queue: Florin Malita <fmalita@google.com>
Commit-Queue: Avery Musbach <amusbach@chromium.org>
Prior to this fix, the new test cases would report that the various loop
terms needed to be constant expressions.
Bug: skia:12472
Change-Id: Ic377ed0c4598136ae38fb2b65c93b6d8609d54cb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452276
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This is mostly to satisfy my curiousity about GPU+SwiftShader vs. CPU
Change-Id: I140ba51f99fead7b4709385396e55f2fcc57ae05
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452196
Commit-Queue: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Auto-Submit: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This reverts commit 0541a983ef.
Reason for revert: Android roll failing
Original change's description:
> bench: Add PhoneHub assets to skottie-vs-png decode bench
>
> The skottie-vs-png decode bench is intended to facilitate comparison
> between Lottie and PNG, but such a comparison cannot really be made when
> the Lottie files are unrelated to the PNG files (Lottie files chosen to
> represent a range of vector graphic complexity, versus PNG files chosen
> to represent a range of image dimensions). This CL adds PhoneHub assets
> in PNG and Lottie, including various Lottie files created using
> different optimization strategies (see added code comments for details).
>
> Change-Id: I1a4357ab0af22b9db7b7ce83fd07d48c77db7680
> Bug: chromium:1128684
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/442476
> Reviewed-by: Avery Musbach <amusbach@google.com>
> Reviewed-by: Florin Malita <fmalita@google.com>
> Commit-Queue: Florin Malita <fmalita@google.com>
Bug: chromium:1128684
Change-Id: Ib6364a482cfff5ca63e74eeb24c2688e49bc4b72
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452096
Auto-Submit: Brian Osman <brianosman@google.com>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bug: skia:12466
Change-Id: I5cca024b8df9cf2203d5f09109154d02f0490445
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451417
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Eric Boren <borenet@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
Dawn is adding an dependency on Abseil, and a previous attempt to do so
broke the Dawn/Skia roller. Adding the library to DEPS here to support
that, though it will only be called from Dawn code (like Tint).
See: https://dawn-review.googlesource.com/c/dawn/+/64600
Bug: dawn:563
Change-Id: I002a086b3c8406da2a59d04321e9189f09e9e29a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451638
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This makes "dm --config grgl --src gm skp" generate a lot of green pngs and adds a stub class for Image_Graphite.
Bug: skia:12466
Change-Id: Ia7cf891ad278434f473cf6c9c4673bf8fa085adf
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451740
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
The only actual use of Compiler is in dsl::ReleaseProgram. All other
uses of Compiler in DSLWriter were to gain access to its internal
IRGenerator.
Change-Id: I0169cb1debf837894b1be3321f3d920259f7e91a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451741
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This should allow lightweight DSL usage without needing access to a
Compiler, but some operations won't work (for now) because they rely on
the IRGenerator. Ideally, as we will reduce our dependence on
IRGenerator, these limitations will fade away.
Change-Id: I93880f153a7425b208bdc4a866169d037e4553a6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451739
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
PossibleExpression / PossibleStatement should only have been used in
cases where we do not have a position available.
Change-Id: I8cd3cafce21b3c18f03e75a0c822eea75c86f225
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451896
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Device will own and manage a BoundsManager, which it will use to decide
the sort and test Z's that it passes to the DrawCommandList in its
draw() implementations.
DrawCommandList might end up being owned by the SDC, with the SDC
exposing a similar drawing API. There will need to be some mechanism to
end a DrawCommandList and start a new one (the list moves into an
SDCTask). This would either happen from an external flush call, or in
the rare case where the representable Z values are exhausted and we
have to insert a depth buffer clear and start a new task that depends
on the prior one.
Bug: skia:12466
Change-Id: I892b631037dc801eb94da2462683c9701afa281b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451599
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Local coordinates are mapped to the SK_MAIN_COORDS_BUILTIN argument in
ProgramToSkVM, and never otherwise needed during code generation.
Change-Id: Ia2080dd72d43fe792881f5422f811e8f35e85572
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451744
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Previously, the ctor for SkVMGenerator did a lot of setup work and
emitted the global-variable logic directly. Callers were responsible for
calling `writeFunction` exactly one time, to emit main.
Now, the ctor of SkVMGenerator just sets up members, and callers need to
call `writeProgram`. `writeProgram` emits all the setup code as well as
main.
This makes the ctor a little less scary looking, and gives us a natural
place to insert a dsl::Start/End pair.
Change-Id: I713a0ea70def64f9eeeda4eb7504028112b5d7ad
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451743
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Herb Derby <herb@google.com>
For this initial landing, we actually have the memoryless support
disabled because we need to update Chrome's vk memory allocator to
handle the new lazy flag added in this CL. Otherwise we will fail to
make dmsaa attachments and not draw anything.
I tested this on ARM and the it does look to keep the size of all the
lazy msaa attachments at 0. I test with both 4 and 8 sample counts. To
confirm the size check, I changed the store op on the msaa attachments
from discard to store and the reported memory size did grow.
Bug: skia:11809
Change-Id: I977f337b922cdbdbce16d67945369246e3547c17
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451296
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This flag is not necessary, and it prevents users with CPUs that do not
support SSSE3 from using design tools in Android Studio.
Change-Id: Ia3b907c6f398e331f642256774116fbf720581da
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/445937
Reviewed-by: Leon Scroggins <scroggo@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
The skottie-vs-png decode bench is intended to facilitate comparison
between Lottie and PNG, but such a comparison cannot really be made when
the Lottie files are unrelated to the PNG files (Lottie files chosen to
represent a range of vector graphic complexity, versus PNG files chosen
to represent a range of image dimensions). This CL adds PhoneHub assets
in PNG and Lottie, including various Lottie files created using
different optimization strategies (see added code comments for details).
Change-Id: I1a4357ab0af22b9db7b7ce83fd07d48c77db7680
Bug: chromium:1128684
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/442476
Reviewed-by: Avery Musbach <amusbach@google.com>
Reviewed-by: Florin Malita <fmalita@google.com>
Commit-Queue: Florin Malita <fmalita@google.com>
The script was previously checking to ensure that each entry was well
formatted, but then continued to try and parse it as if it was
regardless, causing an IndexError when trying to access the split array.
This change continues to the next iteration of the loop when an errors
is detected so that the script can complete normally and the errors can
be reported.
Change-Id: I830c74610ccce45e32a1afa679af7b0ee0881a4e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451637
Reviewed-by: Eric Boren <borenet@google.com>
Commit-Queue: Eric Boren <borenet@google.com>
This is a reland of 828987893b
Addendum: I failed to make the distinction between AVX and FMA.
A machine can have AVX, but not have FMA. We encapsulate this
difference where HSW and SKX are assumed to have FMA while plain
AVX does not.
Original change's description:
> align the different implementations of 1/x
>
> Before this CL, the current rcp (1/x) calculation has enough precision
> for color calculations, but not enough for positional calculations.
>
> Introduce a new reciprocal called recip that has more precision for
> positions. On Intel, this requires the addition of a Newton-Raphson
> iterations, and ARM requires two NR iterations.
>
> Bug = skia:12453
> Change-Id: Ib04d71a653ad1326dc114316c1e909fe4d3d364c
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/449194
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Herb Derby <herb@google.com>
Change-Id: If87764cc57319ddd3254aab2190e0a2b31af099b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451737
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This was replaced by Type::coerceExpression. This CL removes the last
two call sites to reference the old `coerce` method.
Change-Id: I636501a6eb6991463e1975ac38169dee058cdf6f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451738
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Came across this when working on a new GM that happened to use a 1px
wide image with decal sampling, this caused it to smear across a much
larger than expected area.
Change-Id: I05a12e4ae9a2a54f8a9a18050573a4f6b35197ac
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451357
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Auto-Submit: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Change-Id: I4471903f20b8167b71f81db91748794c7fbfb94b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451576
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Change-Id: Ib0c79046044f159b35f0cbaf06c7931c37a09ac4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451299
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
9184973fc1..68c0da839b
2021-09-22 timvp@google.com Vulkan: Inform frontend when new buffer is allocated
2021-09-22 timvp@google.com Vulkan: glMapBuffer(): Create new buffer (Buffer Ghosting)
2021-09-22 timvp@google.com Vulkan: Add ResourceWrite to track Read and Write Access
2021-09-21 jmadill@chromium.org Vulkan: Lift DS feedback read-only suppression.
2021-09-21 kpiddington@apple.com Metal: ANGLE Metal AutoObjCPtr == nullptr comparison is inverted
2021-09-21 kpiddington@apple.com Reimplement transform feedback on direct-to-Metal backend
2021-09-21 yuxinhu@google.com Fix app trace heap buffer overflow
2021-09-21 jmadill@chromium.org GN: Remove the "no GTest" dEQP targets.
2021-09-21 kpiddington@apple.com Metal Direct: TinyDepthStencilWorkaroundTest.DepthTexturesStick
2021-09-21 jmadill@chromium.org Fix build in some configurations.
2021-09-21 jmadill@chromium.org Perf Tests: Split samples into sub-tests on desktop.
2021-09-21 angle-autoroll@skia-public.iam.gserviceaccount.com Roll SwiftShader from b7de6caa43b9 to 6cbc24686901 (7 revisions)
2021-09-21 angle-autoroll@skia-public.iam.gserviceaccount.com Roll Chromium from e515fa6a510e to 0537997114eb (434 revisions)
If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/angle-skia-autoroll
Please CC brianosman@google.com on the revert to ensure that a human
is aware of the problem.
To file a bug in ANGLE: https://bugs.chromium.org/p/angleproject/issues/entry
To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry
To report a problem with the AutoRoller itself, please file a bug:
https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug
Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Cq-Include-Trybots: skia/skia.primary:Build-Debian10-Clang-x86_64-Release-ANGLE;skia/skia.primary:Test-Win10-Clang-AlphaR2-GPU-RadeonR9M470X-x86_64-Debug-All-ANGLE;skia/skia.primary:Test-Win10-Clang-Golo-GPU-QuadroP400-x86_64-Debug-All-ANGLE;skia/skia.primary:Test-Win10-Clang-NUC5i7RYH-GPU-IntelIris6100-x86_64-Debug-All-ANGLE;skia/skia.primary:Test-Win10-Clang-NUC6i5SYK-GPU-IntelIris540-x86_64-Debug-All-ANGLE;skia/skia.primary:Test-Win10-Clang-NUC8i5BEK-GPU-IntelIris655-x86_64-Debug-All-ANGLE;skia/skia.primary:Test-Win10-Clang-NUCD34010WYKH-GPU-IntelHD4400-x86_64-Debug-All-ANGLE
Tbr: brianosman@google.com
Test: Test: BufferDataTest.MapWriteArrayBufferDataDrawArrays
Test: Test: BufferDataTest.MapWriteArrayBufferDataDrawQuad
Test: Test: ComputeShaderTest.ImageBufferMapWrite
Test: Test: TextureBufferTestES31.MapTextureBufferInvalidateThenWrite
Test: Test: VulkanPerformanceCounterTest.MappingGpuReadOnlyBufferGhostsBuffer
Change-Id: I1ecaef225b0e0c62167d20f833d6e58305636358
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451438
Commit-Queue: skia-autoroll <skia-autoroll@skia-public.iam.gserviceaccount.com>
Bot-Commit: skia-autoroll <skia-autoroll@skia-public.iam.gserviceaccount.com>
This reverts commit 828987893b.
Reason for revert: breaks Waymo
Original change's description:
> align the different implementations of 1/x
>
> Before this CL, the current rcp (1/x) calculation has enough precision
> for color calculations, but not enough for positional calculations.
>
> Introduce a new reciprocal called recip that has more precision for
> positions. On Intel, this requires the addition of a Newton-Raphson
> iterations, and ARM requires two NR iterations.
>
> Bug = skia:12453
> Change-Id: Ib04d71a653ad1326dc114316c1e909fe4d3d364c
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/449194
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Herb Derby <herb@google.com>
Change-Id: I555fead21dc8b856cc6f0a1b59b14176a1ba2bfd
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451356
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Change-Id: Icdeb0e3efce2cd9ba697edebe1c3a831144c7613
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451256
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
and fix up the #include guards
Bug: skia:12466
Change-Id: I865ebb00827001b2cf0f7d871e872a7be0f36c22
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451156
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
It looks like returning from inside a switch on iOS gives wrong results
in GLSL.
Change-Id: I9d6d8971a7a54600268e27443815444fca6f3c61
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/450994
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Before this CL, the current rcp (1/x) calculation has enough precision
for color calculations, but not enough for positional calculations.
Introduce a new reciprocal called recip that has more precision for
positions. On Intel, this requires the addition of a Newton-Raphson
iterations, and ARM requires two NR iterations.
Bug = skia:12453
Change-Id: Ib04d71a653ad1326dc114316c1e909fe4d3d364c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/449194
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This fails on several platforms in practice, and is of very limited
real-world utility.
Change-Id: Ib476396fc33cb51af6bbcf7fe822d30703ed995d
Bug: skia:12467
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/450993
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Per spec, reading anything other than the most recently written
union member is undefined behavior.
Keyframe containers always access the same member, consistently. But
the type-agnostic equality operator does touch both members.
Refactor to avoid undefined behavior.
Also add a couple of unit tests to capture keyframe deduping behavior
(which in turn relies on the equality operator).
Change-Id: I7ba9c335ef28af7ddc71bd6f03d56b891fbdea1e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451016
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Florin Malita <fmalita@google.com>
Change-Id: I17b5e21a28140b8e9313d87af9b1145674214fdb
Bug: skia:12450
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/450989
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Change-Id: Ice0826af0b64fa8dd92975f879af8ab0f71740fc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451039
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
fed5521016..6190360967
Contains a change that accepts ClipBoxes only in format number 0 instead
of 1 after a spec change to harmonize format numbering, thus needs
an update to the test font.
Change-Id: I837802648aec1acc0d0424b2b381e3f7031b181e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/450916
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>