Bug 793175: Discard a cached SourceSurface if it was created for the wrong BackendType. r=jrmuizel
☠☠ backed out by 08bf91d3c0c3 ☠ ☠
authorBas Schouten <bas.schouten@live.nl>
Mon, 08 Oct 2012 15:44:36 +1300
changeset 109610 6c89d2b6ea4bc4b9ce78b4962764156d7c2f717a
parent 109609 9157b71a7df1fcb50b22e23e724befc6e2de4613
child 109611 20899bf876464a1e487e3e8b867e452c740a87db
push id23636
push usergsharp@mozilla.com
push dateMon, 08 Oct 2012 08:08:19 +0000
treeherdermozilla-central@24cf40690042 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs793175
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;