Bug 937145 - Allow Moz2D recordings to grab the existing content of a DrawTarget. r=BenWa
authorBas Schouten <bschouten@mozilla.com>
Wed, 27 Nov 2013 12:21:57 +0100
changeset 157796 5dd203b2ebbb1707d5553b802036af2ba0eb997c
parent 157795 6cc4f7c7180f745493025939fd3baa0865066252
child 157797 d5bc7ed8af530e711d2216f3e954729e3cd49ba6
push id25726
push usercbook@mozilla.com
push dateThu, 28 Nov 2013 10:47:25 +0000
treeherdermozilla-central@cdca43b7657d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa
bugs937145
milestone28.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 937145 - Allow Moz2D recordings to grab the existing content of a DrawTarget. r=BenWa
gfx/2d/DrawTargetRecording.cpp
gfx/2d/DrawTargetRecording.h
gfx/2d/Factory.cpp
gfx/2d/RecordedEvent.cpp
gfx/2d/RecordedEvent.h
--- a/gfx/2d/DrawTargetRecording.cpp
+++ b/gfx/2d/DrawTargetRecording.cpp
@@ -134,21 +134,23 @@ struct AdjustedPattern
     char mRadGradPat[sizeof(RadialGradientPattern)];
     char mSurfPat[sizeof(SurfacePattern)];
   };
 
   Pattern *mOrigPattern;
   Pattern *mPattern;
 };
 
-DrawTargetRecording::DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT)
+DrawTargetRecording::DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData)
   : mRecorder(static_cast<DrawEventRecorderPrivate*>(aRecorder))
   , mFinalDT(aDT)
 {
-  mRecorder->RecordEvent(RecordedDrawTargetCreation(this, mFinalDT->GetType(), mFinalDT->GetSize(), mFinalDT->GetFormat()));
+  RefPtr<SourceSurface> snapshot = aHasData ? mFinalDT->Snapshot() : nullptr;
+  mRecorder->RecordEvent(RecordedDrawTargetCreation(this, mFinalDT->GetType(), mFinalDT->GetSize(), mFinalDT->GetFormat(),
+                                                    aHasData, snapshot));
   mFormat = mFinalDT->GetFormat();
 }
 
 DrawTargetRecording::~DrawTargetRecording()
 {
   mRecorder->RecordEvent(RecordedDrawTargetDestruction(this));
 }
 
--- a/gfx/2d/DrawTargetRecording.h
+++ b/gfx/2d/DrawTargetRecording.h
@@ -10,17 +10,17 @@
 #include "DrawEventRecorder.h"
 
 namespace mozilla {
 namespace gfx {
 
 class DrawTargetRecording : public DrawTarget
 {
 public:
-  DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT);
+  DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData = false);
   ~DrawTargetRecording();
 
   virtual BackendType GetType() const { return mFinalDT->GetType(); }
 
   virtual TemporaryRef<SourceSurface> Snapshot();
 
   virtual IntSize GetSize() { return mFinalDT->GetSize(); }
 
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -306,17 +306,17 @@ Factory::CreateDrawTargetForData(Backend
     }
 #endif
   default:
     gfxDebug() << "Invalid draw target type specified.";
     return nullptr;
   }
 
   if (mRecorder && retVal) {
-    RefPtr<DrawTarget> recordDT = new DrawTargetRecording(mRecorder, retVal);
+    RefPtr<DrawTarget> recordDT = new DrawTargetRecording(mRecorder, retVal, true);
     return recordDT;
   }
 
   if (!retVal) {
     gfxDebug() << "Failed to create DrawTarget, Type: " << aBackend << " Size: " << aSize;
   }
 
   return retVal;
@@ -412,17 +412,17 @@ Factory::CreateDrawTargetForD3D10Texture
 {
   RefPtr<DrawTargetD2D> newTarget;
 
   newTarget = new DrawTargetD2D();
   if (newTarget->Init(aTexture, aFormat)) {
     RefPtr<DrawTarget> retVal = newTarget;
 
     if (mRecorder) {
-      retVal = new DrawTargetRecording(mRecorder, retVal);
+      retVal = new DrawTargetRecording(mRecorder, retVal, true);
     }
 
     return retVal;
   }
 
   gfxWarning() << "Failed to create draw target for D3D10 texture.";
 
   // Failed
@@ -577,17 +577,17 @@ Factory::CreateDrawTargetForCairoSurface
 #ifdef USE_CAIRO
   RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo();
 
   if (newTarget->Init(aSurface, aSize)) {
     retVal = newTarget;
   }
 
   if (mRecorder && retVal) {
-    RefPtr<DrawTarget> recordDT = new DrawTargetRecording(mRecorder, retVal);
+    RefPtr<DrawTarget> recordDT = new DrawTargetRecording(mRecorder, retVal, true);
     return recordDT;
   }
 #endif
   return retVal;
 }
 
 TemporaryRef<SourceSurface>
 Factory::CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
--- a/gfx/2d/RecordedEvent.cpp
+++ b/gfx/2d/RecordedEvent.cpp
@@ -346,34 +346,60 @@ RecordedDrawingEvent::GetObjectRef() con
 }
 
 void
 RecordedDrawTargetCreation::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<DrawTarget> newDT =
     aTranslator->GetReferenceDrawTarget()->CreateSimilarDrawTarget(mSize, mFormat);
   aTranslator->AddDrawTarget(mRefPtr, newDT);
+
+  if (mHasExistingData) {
+    Rect dataRect(0, 0, mExistingData->GetSize().width, mExistingData->GetSize().height);
+    newDT->DrawSurface(mExistingData, dataRect, dataRect);
+  }
 }
 
 void
 RecordedDrawTargetCreation::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mBackendType);
   WriteElement(aStream, mSize);
   WriteElement(aStream, mFormat);
+  WriteElement(aStream, mHasExistingData);
+
+  if (mHasExistingData) {
+    MOZ_ASSERT(mExistingData);
+    MOZ_ASSERT(mExistingData->GetSize() == mSize);
+    RefPtr<DataSourceSurface> dataSurf = mExistingData->GetDataSurface();
+    for (int y = 0; y < mSize.height; y++) {
+      aStream.write((const char*)dataSurf->GetData() + y * dataSurf->Stride(),
+                    BytesPerPixel(mFormat) * mSize.width);
+    }
+  }
 }
 
 RecordedDrawTargetCreation::RecordedDrawTargetCreation(istream &aStream)
   : RecordedEvent(DRAWTARGETCREATION)
 {
   ReadElement(aStream, mRefPtr);
   ReadElement(aStream, mBackendType);
   ReadElement(aStream, mSize);
   ReadElement(aStream, mFormat);
+  ReadElement(aStream, mHasExistingData);
+
+  if (mHasExistingData) {
+    RefPtr<DataSourceSurface> dataSurf = Factory::CreateDataSourceSurface(mSize, mFormat);
+    for (int y = 0; y < mSize.height; y++) {
+      aStream.read((char*)dataSurf->GetData() + y * dataSurf->Stride(),
+                    BytesPerPixel(mFormat) * mSize.width);
+    }
+    mExistingData = dataSurf;
+  }
 }
 
 void
 RecordedDrawTargetCreation::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] DrawTarget Creation (Type: " << NameFromBackend(mBackendType) << ", Size: " << mSize.width << "x" << mSize.height << ")";
 }
 
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -15,17 +15,17 @@
 
 namespace mozilla {
 namespace gfx {
 
 // A change in major revision means a change in event binary format, causing
 // loss of backwards compatibility. Old streams will not work in a player
 // using a newer major revision. And new streams will not work in a player
 // using an older major revision.
-const uint16_t kMajorRevision = 2;
+const uint16_t kMajorRevision = 3;
 // A change in minor revision means additions of new events. New streams will
 // not play in older players.
 const uint16_t kMinorRevision = 1;
 
 struct ReferencePtr
 {
   ReferencePtr()
     : mLongPtr(0)
@@ -217,32 +217,36 @@ protected:
 
   virtual ReferencePtr GetObjectRef() const;
 
   ReferencePtr mDT;
 };
 
 class RecordedDrawTargetCreation : public RecordedEvent {
 public:
-  RecordedDrawTargetCreation(ReferencePtr aRefPtr, BackendType aType, const IntSize &aSize, SurfaceFormat aFormat)
+  RecordedDrawTargetCreation(ReferencePtr aRefPtr, BackendType aType, const IntSize &aSize, SurfaceFormat aFormat,
+                             bool aHasExistingData = false, SourceSurface *aExistingData = nullptr)
     : RecordedEvent(DRAWTARGETCREATION), mRefPtr(aRefPtr), mBackendType(aType), mSize(aSize), mFormat(aFormat)
+    , mHasExistingData(aHasExistingData), mExistingData(aExistingData)
   {}
 
   virtual void PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "DrawTarget Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 
   ReferencePtr mRefPtr;
   BackendType mBackendType;
   IntSize mSize;
   SurfaceFormat mFormat;
+  bool mHasExistingData;
+  RefPtr<SourceSurface> mExistingData;
   
 private:
   friend class RecordedEvent;
 
   RecordedDrawTargetCreation(std::istream &aStream);
 };
 
 class RecordedDrawTargetDestruction : public RecordedEvent {