Bug 793175: Discard a cached SourceSurface if it was created for the wrong BackendType. r=jrmuizel
☠☠ backed out by 7b2e2c81e0b9 ☠ ☠
authorBas Schouten <bas.schouten@live.nl>
Mon, 08 Oct 2012 15:44:36 +1300
changeset 113264 41b5180cf6af91e751669e144e7dfa58ae3a0789
parent 113263 5c59fd005fb897b33cceaad689eb6fa28765ff77
child 113265 7b2e2c81e0b94bb58c2427ac485372425a724e45
push id2248
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 19:23:44 +0000
treeherdermozilla-aurora@118a3b748323 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs793175
milestone18.0a1
Bug 793175: Discard a cached SourceSurface if it was created for the wrong BackendType. r=jrmuizel
gfx/thebes/gfxPlatform.cpp
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -484,39 +484,52 @@ gfxPlatform::CreateDrawTargetForSurface(
 {
   RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize);
   aSurface->SetData(&kDrawTarget, drawTarget, NULL);
   return drawTarget;
 }
 
 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<SourceSurface*>(srcBuffer)->Release();
+  RefPtr<SourceSurface> mSrcSurface;
+  BackendType mBackendType;
+};
+
+void SourceBufferDestroy(void *srcSurfUD)
+{
+  delete static_cast<SourceSurfaceUserData*>(srcSurfUD);
 }
 
 void SourceSnapshotDetached(cairo_surface_t *nullSurf)
 {
   gfxImageSurface* origSurf =
     static_cast<gfxImageSurface*>(cairo_surface_get_user_data(nullSurf, &kSourceSurface));
 
   origSurf->SetData(&kSourceSurface, NULL, NULL);
 }
 
 RefPtr<SourceSurface>
 gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
 {
   void *userData = aSurface->GetData(&kSourceSurface);
 
   if (userData) {
-    SourceSurface *surf = static_cast<SourceSurface*>(userData);
+    SourceSurfaceUserData *surf = static_cast<SourceSurfaceUserData*>(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.
   }
 
   SurfaceFormat format;
   if (aSurface->GetContentType() == gfxASurface::CONTENT_ALPHA) {
     format = FORMAT_A8;
@@ -619,17 +632,21 @@ gfxPlatform::GetSourceSurfaceForSurface(
                                 &kSourceSurface,
                                 imgSurface,
                                 NULL);
     cairo_surface_attach_snapshot(imgSurface->CairoSurface(), nullSurf, SourceSnapshotDetached);
     cairo_surface_destroy(nullSurf);
   }
 
   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;
 }
 
 TemporaryRef<ScaledFont>
 gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
   NativeFont nativeFont;