mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 922942 - Add a Validate() pass to BasicLayers to avoid needing to create a dummy destination context. r=roc
This commit is contained in:
parent
762844a6e0
commit
c8d82e8dcd
@ -115,6 +115,20 @@ BasicContainerLayer::ChildrenPartitionVisibleRegion(const nsIntRect& aInRect)
|
|||||||
return covered.Contains(rect);
|
return covered.Contains(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicContainerLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||||
|
void* aCallbackData)
|
||||||
|
{
|
||||||
|
for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
|
||||||
|
BasicImplData* data = ToData(l);
|
||||||
|
data->Validate(aCallback, aCallbackData);
|
||||||
|
if (l->GetMaskLayer()) {
|
||||||
|
data = ToData(l->GetMaskLayer());
|
||||||
|
data->Validate(aCallback, aCallbackData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<ContainerLayer>
|
already_AddRefed<ContainerLayer>
|
||||||
BasicLayerManager::CreateContainerLayer()
|
BasicLayerManager::CreateContainerLayer()
|
||||||
{
|
{
|
||||||
|
@ -76,6 +76,9 @@ public:
|
|||||||
|
|
||||||
void SetSupportsComponentAlphaChildren(bool aSupports) { mSupportsComponentAlphaChildren = aSupports; }
|
void SetSupportsComponentAlphaChildren(bool aSupports) { mSupportsComponentAlphaChildren = aSupports; }
|
||||||
|
|
||||||
|
virtual void Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||||
|
void* aCallbackData) MOZ_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BasicLayerManager* BasicManager()
|
BasicLayerManager* BasicManager()
|
||||||
{
|
{
|
||||||
|
@ -73,6 +73,9 @@ public:
|
|||||||
void* aCallbackData,
|
void* aCallbackData,
|
||||||
ReadbackProcessor* aReadback) {}
|
ReadbackProcessor* aReadback) {}
|
||||||
|
|
||||||
|
virtual void Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||||
|
void* aCallbackData) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layers will get this call when their layer manager is destroyed, this
|
* Layers will get this call when their layer manager is destroyed, this
|
||||||
* indicates they should clear resources they don't really need after their
|
* indicates they should clear resources they don't really need after their
|
||||||
|
@ -581,22 +581,32 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||||||
NS_ASSERTION(InConstruction(), "Should be in construction phase");
|
NS_ASSERTION(InConstruction(), "Should be in construction phase");
|
||||||
mPhase = PHASE_DRAWING;
|
mPhase = PHASE_DRAWING;
|
||||||
|
|
||||||
Layer* aLayer = GetRoot();
|
RenderTraceLayers(mRoot, "FF00");
|
||||||
RenderTraceLayers(aLayer, "FF00");
|
|
||||||
|
|
||||||
mTransactionIncomplete = false;
|
mTransactionIncomplete = false;
|
||||||
|
|
||||||
if (aFlags & END_NO_COMPOSITE) {
|
if (mRoot) {
|
||||||
if (!mDummyTarget) {
|
// Need to do this before we call ApplyDoubleBuffering,
|
||||||
// XXX: We should really just set mTarget to null and make sure we can handle that further down the call chain
|
// which depends on correct effective transforms
|
||||||
// Creating this temporary surface can be expensive on some platforms (d2d in particular), so cache it between paints.
|
mSnapEffectiveTransforms =
|
||||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(1, 1), GFX_CONTENT_COLOR);
|
mTarget ? !(mTarget->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING) : true;
|
||||||
mDummyTarget = new gfxContext(surf);
|
mRoot->ComputeEffectiveTransforms(mTarget ? gfx3DMatrix::From2D(mTarget->CurrentMatrix()) : gfx3DMatrix());
|
||||||
|
|
||||||
|
ToData(mRoot)->Validate(aCallback, aCallbackData);
|
||||||
|
if (mRoot->GetMaskLayer()) {
|
||||||
|
ToData(mRoot->GetMaskLayer())->Validate(aCallback, aCallbackData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aFlags & END_NO_COMPOSITE) {
|
||||||
|
// Apply pending tree updates before recomputing effective
|
||||||
|
// properties.
|
||||||
|
mRoot->ApplyPendingUpdatesToSubtree();
|
||||||
}
|
}
|
||||||
mTarget = mDummyTarget;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
|
if (mTarget && mRoot &&
|
||||||
|
!(aFlags & END_NO_IMMEDIATE_REDRAW) &&
|
||||||
|
!(aFlags & END_NO_COMPOSITE)) {
|
||||||
nsIntRect clipRect;
|
nsIntRect clipRect;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -605,18 +615,6 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||||||
clipRect = ToOutsideIntRect(mTarget->GetClipExtents());
|
clipRect = ToOutsideIntRect(mTarget->GetClipExtents());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aFlags & END_NO_COMPOSITE) {
|
|
||||||
// Apply pending tree updates before recomputing effective
|
|
||||||
// properties.
|
|
||||||
aLayer->ApplyPendingUpdatesToSubtree();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need to do this before we call ApplyDoubleBuffering,
|
|
||||||
// which depends on correct effective transforms
|
|
||||||
mSnapEffectiveTransforms =
|
|
||||||
!(mTarget->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING);
|
|
||||||
mRoot->ComputeEffectiveTransforms(gfx3DMatrix::From2D(mTarget->CurrentMatrix()));
|
|
||||||
|
|
||||||
if (IsRetained()) {
|
if (IsRetained()) {
|
||||||
nsIntRegion region;
|
nsIntRegion region;
|
||||||
MarkLayersHidden(mRoot, clipRect, clipRect, region, ALLOW_OPAQUE);
|
MarkLayersHidden(mRoot, clipRect, clipRect, region, ALLOW_OPAQUE);
|
||||||
@ -625,22 +623,12 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aFlags & END_NO_COMPOSITE) {
|
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
|
||||||
if (IsRetained()) {
|
if (mWidget) {
|
||||||
// Clip the destination out so that we don't draw to it, and
|
FlashWidgetUpdateArea(mTarget);
|
||||||
// only end up validating ThebesLayers.
|
|
||||||
mTarget->Clip(gfxRect(0, 0, 0, 0));
|
|
||||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
|
|
||||||
}
|
|
||||||
// If we're not retained, then don't composite means do nothing at all.
|
|
||||||
} else {
|
|
||||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
|
|
||||||
if (mWidget) {
|
|
||||||
FlashWidgetUpdateArea(mTarget);
|
|
||||||
}
|
|
||||||
RenderDebugOverlay();
|
|
||||||
LayerManager::PostPresent();
|
|
||||||
}
|
}
|
||||||
|
RenderDebugOverlay();
|
||||||
|
LayerManager::PostPresent();
|
||||||
|
|
||||||
if (!mTransactionIncomplete) {
|
if (!mTransactionIncomplete) {
|
||||||
// Clear out target if we have a complete transaction.
|
// Clear out target if we have a complete transaction.
|
||||||
|
@ -186,7 +186,6 @@ protected:
|
|||||||
nsRefPtr<gfxContext> mDefaultTarget;
|
nsRefPtr<gfxContext> mDefaultTarget;
|
||||||
// The context to draw into.
|
// The context to draw into.
|
||||||
nsRefPtr<gfxContext> mTarget;
|
nsRefPtr<gfxContext> mTarget;
|
||||||
nsRefPtr<gfxContext> mDummyTarget;
|
|
||||||
// Image factory we use.
|
// Image factory we use.
|
||||||
nsRefPtr<ImageFactory> mFactory;
|
nsRefPtr<ImageFactory> mFactory;
|
||||||
|
|
||||||
|
@ -90,21 +90,11 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
|||||||
NS_ASSERTION(BasicManager()->InDrawing(),
|
NS_ASSERTION(BasicManager()->InDrawing(),
|
||||||
"Can only draw in drawing phase");
|
"Can only draw in drawing phase");
|
||||||
|
|
||||||
if (!mContentClient) {
|
|
||||||
// we pass a null pointer for the Forwarder argument, which means
|
|
||||||
// this will not have a ContentHost on the other side.
|
|
||||||
mContentClient = new ContentClientBasic(nullptr, BasicManager());
|
|
||||||
}
|
|
||||||
|
|
||||||
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
||||||
if (aReadback && UsedForReadback()) {
|
if (aReadback && UsedForReadback()) {
|
||||||
aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
|
aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canUseOpaqueSurface = CanUseOpaqueSurface();
|
|
||||||
ContentType contentType =
|
|
||||||
canUseOpaqueSurface ? GFX_CONTENT_COLOR :
|
|
||||||
GFX_CONTENT_COLOR_ALPHA;
|
|
||||||
float opacity = GetEffectiveOpacity();
|
float opacity = GetEffectiveOpacity();
|
||||||
gfxContext::GraphicsOperator mixBlendMode = GetEffectiveMixBlendMode();
|
gfxContext::GraphicsOperator mixBlendMode = GetEffectiveMixBlendMode();
|
||||||
|
|
||||||
@ -158,54 +148,6 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
uint32_t flags = 0;
|
|
||||||
#ifndef MOZ_WIDGET_ANDROID
|
|
||||||
if (BasicManager()->CompositorMightResample()) {
|
|
||||||
flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
|
|
||||||
}
|
|
||||||
if (!(flags & ThebesLayerBuffer::PAINT_WILL_RESAMPLE)) {
|
|
||||||
if (MayResample()) {
|
|
||||||
flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (mDrawAtomically) {
|
|
||||||
flags |= ThebesLayerBuffer::PAINT_NO_ROTATION;
|
|
||||||
}
|
|
||||||
PaintState state =
|
|
||||||
mContentClient->BeginPaintBuffer(this, contentType, flags);
|
|
||||||
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
|
|
||||||
|
|
||||||
if (state.mContext) {
|
|
||||||
// The area that became invalid and is visible needs to be repainted
|
|
||||||
// (this could be the whole visible area if our buffer switched
|
|
||||||
// from RGB to RGBA, because we might need to repaint with
|
|
||||||
// subpixel AA)
|
|
||||||
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
|
|
||||||
GetEffectiveVisibleRegion());
|
|
||||||
nsIntRegion extendedDrawRegion = state.mRegionToDraw;
|
|
||||||
SetAntialiasingFlags(this, state.mContext);
|
|
||||||
|
|
||||||
RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
|
|
||||||
|
|
||||||
PaintBuffer(state.mContext,
|
|
||||||
state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
|
|
||||||
state.mDidSelfCopy,
|
|
||||||
aCallback, aCallbackData);
|
|
||||||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
|
|
||||||
Mutated();
|
|
||||||
|
|
||||||
RenderTraceInvalidateEnd(this, "FFFF00");
|
|
||||||
} else {
|
|
||||||
// It's possible that state.mRegionToInvalidate is nonempty here,
|
|
||||||
// if we are shrinking the valid region to nothing. So use mRegionToDraw
|
|
||||||
// instead.
|
|
||||||
NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
|
|
||||||
"No context when we have something to draw, resource exhaustion?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BasicManager()->IsTransactionIncomplete())
|
if (BasicManager()->IsTransactionIncomplete())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -242,6 +184,72 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||||
|
void* aCallbackData)
|
||||||
|
{
|
||||||
|
if (!mContentClient) {
|
||||||
|
// we pass a null pointer for the Forwarder argument, which means
|
||||||
|
// this will not have a ContentHost on the other side.
|
||||||
|
mContentClient = new ContentClientBasic(nullptr, BasicManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BasicManager()->IsRetained()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool canUseOpaqueSurface = CanUseOpaqueSurface();
|
||||||
|
ContentType contentType =
|
||||||
|
canUseOpaqueSurface ? GFX_CONTENT_COLOR :
|
||||||
|
GFX_CONTENT_COLOR_ALPHA;
|
||||||
|
|
||||||
|
uint32_t flags = 0;
|
||||||
|
#ifndef MOZ_WIDGET_ANDROID
|
||||||
|
if (BasicManager()->CompositorMightResample()) {
|
||||||
|
flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
|
||||||
|
}
|
||||||
|
if (!(flags & ThebesLayerBuffer::PAINT_WILL_RESAMPLE)) {
|
||||||
|
if (MayResample()) {
|
||||||
|
flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (mDrawAtomically) {
|
||||||
|
flags |= ThebesLayerBuffer::PAINT_NO_ROTATION;
|
||||||
|
}
|
||||||
|
PaintState state =
|
||||||
|
mContentClient->BeginPaintBuffer(this, contentType, flags);
|
||||||
|
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
|
||||||
|
|
||||||
|
if (state.mContext) {
|
||||||
|
// The area that became invalid and is visible needs to be repainted
|
||||||
|
// (this could be the whole visible area if our buffer switched
|
||||||
|
// from RGB to RGBA, because we might need to repaint with
|
||||||
|
// subpixel AA)
|
||||||
|
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
|
||||||
|
GetEffectiveVisibleRegion());
|
||||||
|
nsIntRegion extendedDrawRegion = state.mRegionToDraw;
|
||||||
|
SetAntialiasingFlags(this, state.mContext);
|
||||||
|
|
||||||
|
RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
|
||||||
|
|
||||||
|
PaintBuffer(state.mContext,
|
||||||
|
state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
|
||||||
|
state.mDidSelfCopy,
|
||||||
|
aCallback, aCallbackData);
|
||||||
|
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
|
||||||
|
Mutated();
|
||||||
|
|
||||||
|
RenderTraceInvalidateEnd(this, "FFFF00");
|
||||||
|
} else {
|
||||||
|
// It's possible that state.mRegionToInvalidate is nonempty here,
|
||||||
|
// if we are shrinking the valid region to nothing. So use mRegionToDraw
|
||||||
|
// instead.
|
||||||
|
NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
|
||||||
|
"No context when we have something to draw, resource exhaustion?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<ThebesLayer>
|
already_AddRefed<ThebesLayer>
|
||||||
BasicLayerManager::CreateThebesLayer()
|
BasicLayerManager::CreateThebesLayer()
|
||||||
{
|
{
|
||||||
|
@ -64,6 +64,9 @@ public:
|
|||||||
void* aCallbackData,
|
void* aCallbackData,
|
||||||
ReadbackProcessor* aReadback);
|
ReadbackProcessor* aReadback);
|
||||||
|
|
||||||
|
virtual void Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
||||||
|
void* aCallbackData) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual void ClearCachedResources()
|
virtual void ClearCachedResources()
|
||||||
{
|
{
|
||||||
if (mContentClient) {
|
if (mContentClient) {
|
||||||
|
Loading…
Reference in New Issue
Block a user