From a813e80bc28352d3bb01bd19a679e79b77758892 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Mon, 8 Oct 2012 15:44:36 +1300 Subject: [PATCH] Bug 793175: Discard a cached SourceSurface if it was created for the wrong BackendType. r=jrmuizel --- gfx/thebes/gfxPlatform.cpp | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 14dd72a1b39..055da4fd548 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -489,9 +489,22 @@ gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aS cairo_user_data_key_t kSourceSurface; -void SourceBufferDestroy(void *srcBuffer) +/** + * Record the backend that was used to construct the SourceSurface. + * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair, + * we check to make sure the DrawTarget's backend matches the backend + * for the cached SourceSurface, and only use it if they match. This + * can avoid expensive and unnecessary readbacks. + */ +struct SourceSurfaceUserData { - static_cast(srcBuffer)->Release(); + RefPtr mSrcSurface; + BackendType mBackendType; +}; + +void SourceBufferDestroy(void *srcSurfUD) +{ + delete static_cast(srcSurfUD); } void SourceSnapshotDetached(cairo_surface_t *nullSurf) @@ -508,10 +521,10 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa void *userData = aSurface->GetData(&kSourceSurface); if (userData) { - SourceSurface *surf = static_cast(userData); + SourceSurfaceUserData *surf = static_cast(userData); - if (surf->IsValid()) { - return surf; + if (surf->mSrcSurface->IsValid() && surf->mBackendType == aTarget->GetType()) { + return surf->mSrcSurface; } // We can just continue here as when setting new user data the destroy // function will be called for the old user data. @@ -624,7 +637,11 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa } srcBuffer->AddRef(); - aSurface->SetData(&kSourceSurface, srcBuffer, SourceBufferDestroy); + + SourceSurfaceUserData *srcSurfUD = new SourceSurfaceUserData; + srcSurfUD->mBackendType = aTarget->GetType(); + srcSurfUD->mSrcSurface = srcBuffer; + aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy); return srcBuffer; }