W3C home > Mailing lists > Public > public-fx@w3.org > July to September 2016

Re: [css-transforms] CSS3D breaks with opacity flattening

From: Tien-Ren Chen <trchen@chromium.org>
Date: Wed, 21 Sep 2016 17:03:04 -0700
Message-ID: <CAKxkHO8xEjNzM-01TkKBQeQTU8c5r0qo95vPTu4pDMnC58OdfA@mail.gmail.com>
To: "Tab Atkins Jr." <jackalmage@gmail.com>
Cc: Matt Woodrow <mwoodrow@mozilla.com>, Rik Cabanier <cabanier@gmail.com>, "/#!/JoePea" <trusktr@gmail.com>, Chris Harrelson <chrishtr@google.com>, Simon Fraser <simon.fraser@apple.com>, "public-fx@w3.org" <public-fx@w3.org>
On Wed, Sep 21, 2016 at 12:02 AM, Tab Atkins Jr. <jackalmage@gmail.com> wrote:
> translateZ() and z-index should
> work similarly, as they're doing the same thing.

I don't agree with you. IMO a 3D transform should pop the subtree to a
new plane if inside of a 3D context. e.g.

<style> div { transform-style: preserve-3d; } </style>
<div style="position:relative; z-index:0;">
    Plane A
    <div style="transform:translateZ(0);">Plane B</div>
    <div style="z-index:1;">Plane A too</div>
</div>

Should be treated the same as:

<style> div { transform-style: preserve-3d; } </style>
<div style="position:relative; z-index:0;">
    Plane A
    <div style="z-index:1;">Plane A too</div>
</div>
<div style="transform:translateZ(0);">Plane B</div>

This will avoid having to deal with the transition between
translateZ(-epsilon) / translateZ(0) / translateZ(epsilon) in case of
an animation, which incurs a huge runtime cost because every stacking
context after a transformed child will need to be cached separately.

In my mental model, this is how a compositing tree should look like:

Output = StackingContext
StackingContext = NormalFlowBackground + Child* + NormalFlowForeground
+ Child* [#1]
     || flatten( 3dContext )
     || grouping_property( StackingContext )
Child = StackingContext || PseudoStackingContext
PseudoStackingContext = NormalFlowBackground + NormalFlowForeground
3dContext = Plane*
Plane = StackingContext, Matrix44

Note #1: Operator+ is our typical src-over. In case of CSS blending,
replace operator+ with appropriate operator.

Basically each StackingContext physically is an array of RGBA pixels.

Combined with a Matrix44 give each pixel a depth, each Plane
physically is an array of RGBAD pixels. Flattening operation takes a
list of planes, and src-over (or blend) each pixels depth-sorted  (in
case of a tie, stacking context order is used to break the tie.). The
actual implementation will most likely do polygon splitting, as
performing a sort on each pixel over a number of planes would be
prohibitively expensive.

And I would spec the painting order of elements with this decision tree:
---- z-index: auto ---
1. An element paints as the normal flow of the current (pseudo)
stacking context if the element has z-index:auto and position:static.
2. An element establishes a pseudo stacking context if it has
z-index:auto and position other than static. This new pseudo stacking
context sorts into current stacking context as if z-index is 0.
--- non-auto z-index, with no 3D[#2] transform ---
3. An element establishes a stacking context if it has non-auto
z-index and no 3D transform. This new stacking context become the
current stacking context and sorts into previous stacking context by
z-index value.
--- 3D transformed ---
4. An element establishes a stacking context if it has 3D transform
and both itself and its containing block have transform-style:flat.
The depth part of the transform is discarded and behave like case 3.
5. An element establishes a plane and a stacking context if it has 3D
transform and its containing block has transform-style:preserve-3d.
This new plane joins the current 3D context, and the new stacking
context becomes the root stacking context of the new plane. The
z-index is unused except for tie breaking.
6. An element establishes a 3D context, a plane and a stacking context
if it has transform-style:preserve-3d and its containing block has
transform-style:flat. This new 3D context will flatten its planes and
become a child stacking context that sorts into current stacking
context by z-index value. This new plane joins the new 3D context, and
the new stacking context becomes the root stacking context of the new
plane. [#3]

Note #2: There is a discrepancy in the definition of 3D-ness of
transforms. Firefox & Edge uses the computed local matrix. Blink &
WebKit see whether a 3D operation is used in the property.
Note #3: We can see in this case actually two stacking contexts are
created. It is unspecified in the current spec whether grouping
properties apply to the flattened output or the root stacking context
of the new plane. Behavior is inconsistent across vendors.
Received on Thursday, 22 September 2016 00:03:38 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:49:57 UTC