Bug 748088 - Part 2: Drawing to a non-default target should happen on the shadow side, not the shadowable side. r=BenWa

This commit is contained in:
Ali Juma 2012-06-01 08:42:36 -04:00
parent f5a079ba1b
commit 476ae36564
5 changed files with 64 additions and 0 deletions

View File

@ -3509,11 +3509,26 @@ void
BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
nsRefPtr<gfxContext> targetContext = aTarget;
// If the last transaction was incomplete (a failed DoEmptyTransaction),
// don't signal a new transaction to ShadowLayerForwarder. Carry on adding
// to the previous transaction.
if (HasShadowManager()) {
ShadowLayerForwarder::BeginTransaction();
// If we have a non-default target, we need to let our shadow manager draw
// to it. This will happen at the end of the transaction.
if (aTarget && (aTarget != mDefaultTarget)) {
mShadowTarget = aTarget;
// Create a temporary target for ourselves, so that mShadowTarget is only
// drawn to by our shadow manager.
nsRefPtr<gfxASurface> targetSurface = gfxPlatform::GetPlatform()->
CreateOffscreenSurface(aTarget->OriginalSurface()->GetSize(),
aTarget->OriginalSurface()->GetContentType());
targetContext = new gfxContext(targetSurface);
}
}
BasicLayerManager::BeginTransactionWithTarget(aTarget);
}
@ -3525,6 +3540,10 @@ BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
{
BasicLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
ForwardTransaction();
if (mShadowTarget) {
ShadowLayerForwarder::ShadowDrawToTarget(mShadowTarget);
mShadowTarget = nsnull;
}
}
bool

View File

@ -177,6 +177,8 @@ protected:
nsRefPtr<gfxContext> mDefaultTarget;
// The context to draw into.
nsRefPtr<gfxContext> mTarget;
// A context we want our shadow to draw into.
nsRefPtr<gfxContext> mShadowTarget;
// Image factory we use.
nsRefPtr<ImageFactory> mFactory;

View File

@ -343,6 +343,28 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
return true;
}
bool
ShadowLayerForwarder::ShadowDrawToTarget(gfxContext* aTarget) {
SurfaceDescriptor descriptorIn, descriptorOut;
AllocBuffer(aTarget->OriginalSurface()->GetSize(),
aTarget->OriginalSurface()->GetContentType(),
&descriptorIn);
if (!mShadowManager->SendDrawToSurface(descriptorIn, &descriptorOut)) {
return false;
}
nsRefPtr<gfxASurface> surface = OpenDescriptor(descriptorOut);
aTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
aTarget->DrawSurface(surface, surface->GetSize());
surface = nsnull;
DestroySharedSurface(&descriptorOut);
return true;
}
static SharedMemory::SharedMemoryType
OptimalShmemType()
{

View File

@ -194,6 +194,11 @@ public:
*/
bool EndTransaction(InfallibleTArray<EditReply>* aReplies);
/**
* Composite ShadowLayerManager's layer tree into aTarget.
*/
bool ShadowDrawToTarget(gfxContext* aTarget);
/**
* Set an actor through which layer updates will be pushed.
*/

View File

@ -415,6 +415,22 @@ ShadowLayersParent::RecvDrawToSurface(const SurfaceDescriptor& surfaceIn,
SurfaceDescriptor* surfaceOut)
{
*surfaceOut = surfaceIn;
if (mDestroyed || layer_manager()->IsDestroyed()) {
return true;
}
nsRefPtr<gfxASurface> sharedSurface = ShadowLayerForwarder::OpenDescriptor(surfaceIn);
nsRefPtr<gfxASurface> localSurface =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(sharedSurface->GetSize(),
sharedSurface->GetContentType());
nsRefPtr<gfxContext> context = new gfxContext(localSurface);
layer_manager()->BeginTransactionWithTarget(context);
layer_manager()->EndTransaction(NULL, NULL);
nsRefPtr<gfxContext> contextForCopy = new gfxContext(sharedSurface);
contextForCopy->SetOperator(gfxContext::OPERATOR_SOURCE);
contextForCopy->DrawSurface(localSurface, localSurface->GetSize());
return true;
}