Bug 1097464 - Part 6: Handle preserves-3d by compositor. r=roc

Remove WrapPreserve3DList() and replaced it by creating a
nsDisplayTransform item for each transformed frame.

 - Add an additional item for each top frame extending 3D context to
   separate consequence contexts.

 - Effective transform of a layer is the accumulation of ancestors in
   the same 3D context.

 - The layers creating new context and extended by children need a
   temporary buffer if it's effective transform is not 2D.

 - Clip rects are accumulated along the context chain.

 - Visible rects of items are computed from dirty regions of the frame
   creating the context and accumulated transforms.

 - Bounds of items are computed from accumulated transforms and
   accumulated bounds of the descent frames.

 - Backface hidden is handled by compositor and BasicLayerManager.
This commit is contained in:
Thinker K.F. Li
2015-09-17 03:31:00 +02:00
parent 9e548da5a7
commit af80f65bac
14 changed files with 858 additions and 291 deletions

View File

@@ -811,7 +811,15 @@ BasicLayerManager::PaintSelfOrChildren(PaintLayerContext& aPaintContext,
nsAutoTArray<Layer*, 12> children;
container->SortChildrenBy3DZOrder(children);
for (uint32_t i = 0; i < children.Length(); i++) {
PaintLayer(aGroupTarget, children.ElementAt(i), aPaintContext.mCallback,
Layer* layer = children.ElementAt(i);
if (layer->IsBackfaceHidden()) {
continue;
}
if (!layer->AsContainerLayer() && !layer->IsVisible()) {
continue;
}
PaintLayer(aGroupTarget, layer, aPaintContext.mCallback,
aPaintContext.mCallbackData);
if (mTransactionIncomplete)
break;
@@ -845,6 +853,41 @@ BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext, bool aNeedsClipT
}
}
/**
* Install the clip applied to the layer on the given gfxContext. The
* given gfxContext is the buffer that the layer will be painted to.
*/
static void
InstallLayerClipPreserves3D(gfxContext* aTarget, Layer* aLayer)
{
const Maybe<ParentLayerIntRect> &clipRect = aLayer->GetEffectiveClipRect();
if (!clipRect) {
return;
}
Layer* parent = aLayer->GetParent();
Matrix4x4 transform3d =
parent && parent->Extend3DContext() ?
parent->GetEffectiveTransform() :
Matrix4x4();
Matrix transform;
if (!transform3d.CanDraw2D(&transform)) {
MOZ_CRASH("We should not have a 3D transform that CanDraw2D() is false!");
return;
}
gfxMatrix oldTransform = aTarget->CurrentMatrix();
transform *= ToMatrix(oldTransform);
aTarget->SetMatrix(ThebesMatrix(transform));
aTarget->NewPath();
aTarget->SnappedRectangle(gfxRect(clipRect->x, clipRect->y,
clipRect->width, clipRect->height));
aTarget->Clip();
aTarget->SetMatrix(oldTransform);
}
void
BasicLayerManager::PaintLayer(gfxContext* aTarget,
Layer* aLayer,
@@ -884,17 +927,24 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
gfxMatrix transform;
// Will return an identity matrix for 3d transforms, and is handled separately below.
bool is2D = paintLayerContext.Setup2DTransform();
MOZ_ASSERT(is2D || needsGroup || !container, "Must PushGroup for 3d transforms!");
MOZ_ASSERT(is2D || needsGroup || !container ||
container->Extend3DContext() ||
container->Is3DContextLeaf(),
"Must PushGroup for 3d transforms!");
Layer* parent = aLayer->GetParent();
bool inPreserves3DChain = parent && parent->Extend3DContext();
bool needsSaveRestore =
needsGroup || clipRect || needsClipToVisibleRegion || !is2D;
needsGroup || clipRect || needsClipToVisibleRegion || !is2D ||
inPreserves3DChain;
if (needsSaveRestore) {
contextSR.SetContext(aTarget);
if (clipRect) {
aTarget->NewPath();
aTarget->SnappedRectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height));
aTarget->Clip();
// The clips on ancestors on the preserved3d chain should be
// installed on the aTarget before painting the layer.
InstallLayerClipPreserves3D(aTarget, aLayer);
for (Layer* l = parent; l && l->Extend3DContext(); l = l->GetParent()) {
InstallLayerClipPreserves3D(aTarget, l);
}
}
@@ -929,6 +979,11 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
PaintSelfOrChildren(paintLayerContext, aTarget);
}
} else {
if (!needsGroup && container) {
PaintSelfOrChildren(paintLayerContext, aTarget);
return;
}
const IntRect& bounds = visibleRegion.GetBounds();
RefPtr<DrawTarget> untransformedDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(bounds.width, bounds.height),