Bug 564991. Part 19: Cache the backbuffer surface for performance wins. r=vlad

This commit is contained in:
Robert O'Callahan 2010-07-16 09:08:04 +12:00
Родитель 64934786f8
Коммит b3a05d5100
2 изменённых файлов: 76 добавлений и 4 удалений

Просмотреть файл

@ -612,6 +612,65 @@ BasicLayerManager::BeginTransaction()
BeginTransactionWithTarget(mDefaultTarget);
}
already_AddRefed<gfxContext>
BasicLayerManager::PushGroupWithCachedSurface(gfxContext *aTarget,
gfxASurface::gfxContentType aContent,
gfxPoint *aSavedOffset)
{
gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
aTarget->IdentityMatrix();
nsRefPtr<gfxASurface> currentSurf = aTarget->CurrentSurface();
gfxRect clip = aTarget->GetClipExtents();
clip.RoundOut();
if (mCachedSurface) {
/* Verify the current buffer is valid for this purpose */
if (mCachedSurface->GetContentType() != aContent) {
mCachedSurface = nsnull;
} else {
/* bufferClip should always be {0,0,width,height} of the buffer surface */
if (clip.size.width > mCachedSurfaceSize.width ||
clip.size.height > mCachedSurfaceSize.height) {
mCachedSurface = nsnull;
}
}
}
nsRefPtr<gfxContext> ctx;
if (mCachedSurface) {
ctx = new gfxContext(mCachedSurface);
ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
ctx->Paint();
ctx->SetOperator(gfxContext::OPERATOR_OVER);
} else {
mCachedSurfaceSize = gfxIntSize(clip.size.width, clip.size.height);
mCachedSurface = currentSurf->CreateSimilarSurface(aContent,
mCachedSurfaceSize);
if (!mCachedSurface)
return nsnull;
ctx = new gfxContext(mCachedSurface);
}
/* Align our buffer for the original surface */
ctx->Translate(-clip.pos);
*aSavedOffset = clip.pos;
ctx->Multiply(saveMatrix.Matrix());
return ctx.forget();
}
void
BasicLayerManager::PopGroupWithCachedSurface(gfxContext *aTarget,
const gfxPoint& aSavedOffset)
{
if (!mCachedSurface)
return;
gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
aTarget->IdentityMatrix();
aTarget->SetSource(mCachedSurface, aSavedOffset);
aTarget->Paint();
}
void
BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
@ -633,17 +692,20 @@ BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
#endif
if (mTarget) {
nsRefPtr<gfxContext> finalTarget = mTarget;
gfxPoint cachedSurfaceOffset;
if (mUsingDefaultTarget && mDoubleBuffering != BUFFER_NONE) {
nsRefPtr<gfxASurface> targetSurface = mTarget->CurrentSurface();
mTarget->PushGroup(targetSurface->GetContentType());
mTarget = PushGroupWithCachedSurface(mTarget, targetSurface->GetContentType(),
&cachedSurfaceOffset);
}
PaintLayer(mRoot, aCallback, aCallbackData);
if (mUsingDefaultTarget && mDoubleBuffering != BUFFER_NONE) {
mTarget->PopGroupToSource();
mTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
mTarget->Paint();
finalTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
PopGroupWithCachedSurface(finalTarget, cachedSurfaceOffset);
}
mTarget = nsnull;

Просмотреть файл

@ -120,11 +120,21 @@ private:
DrawThebesLayerCallback aCallback,
void* aCallbackData);
already_AddRefed<gfxContext> PushGroupWithCachedSurface(gfxContext *aTarget,
gfxASurface::gfxContentType aContent,
gfxPoint *aSavedOffset);
void PopGroupWithCachedSurface(gfxContext *aTarget,
const gfxPoint& aSavedOffset);
// The default context for BeginTransaction.
nsRefPtr<gfxContext> mDefaultTarget;
// The context to draw into.
nsRefPtr<gfxContext> mTarget;
// Cached surface for double buffering
nsRefPtr<gfxASurface> mCachedSurface;
gfxIntSize mCachedSurfaceSize;
#ifdef DEBUG
enum TransactionPhase { PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING };
TransactionPhase mPhase;