Bug 1360001. Add back some recording helpers. r=bobowen
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Wed, 26 Apr 2017 16:31:59 -0400
changeset 357014 de635d62079bfc358c85a692d729bf1e33da15ca
parent 357013 9bfbae06d8e2054eb563b5e7b346e29a851a9d8e
child 357015 8f1d4b0a03e4285eeb4b2aa326aea5e4f42edc60
push id31780
push userkwierso@gmail.com
push dateMon, 08 May 2017 20:34:47 +0000
treeherdermozilla-central@bab7046ee2d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbobowen
bugs1360001
milestone55.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 1360001. Add back some recording helpers. r=bobowen These are only going to be used temporarily while we bring up blob images for webrender.
gfx/2d/DrawEventRecorder.cpp
gfx/2d/DrawEventRecorder.h
gfx/2d/InlineTranslator.cpp
gfx/2d/InlineTranslator.h
gfx/2d/RecordedEvent.h
gfx/2d/moz.build
--- a/gfx/2d/DrawEventRecorder.cpp
+++ b/gfx/2d/DrawEventRecorder.cpp
@@ -73,10 +73,45 @@ DrawEventRecorderFile::OpenNew(const cha
 void
 DrawEventRecorderFile::Close()
 {
   MOZ_ASSERT(mOutputFile.is_open());
 
   mOutputFile.close();
 }
 
+DrawEventRecorderMemory::DrawEventRecorderMemory()
+  : DrawEventRecorderPrivate(nullptr)
+{
+  mOutputStream = &mMemoryStream;
+
+  WriteHeader();
+}
+
+void
+DrawEventRecorderMemory::Flush()
+{
+   mOutputStream->flush();
+}
+
+size_t
+DrawEventRecorderMemory::RecordingSize()
+{
+  return mMemoryStream.tellp();
+}
+
+bool
+DrawEventRecorderMemory::CopyRecording(char* aBuffer, size_t aBufferLen)
+{
+  return !!mMemoryStream.read(aBuffer, aBufferLen);
+}
+
+void
+DrawEventRecorderMemory::WipeRecording()
+{
+  mMemoryStream.str(std::string());
+  mMemoryStream.clear();
+
+  WriteHeader();
+}
+
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/2d/DrawEventRecorder.h
+++ b/gfx/2d/DrawEventRecorder.h
@@ -98,12 +98,61 @@ public:
   void Close();
 
 private:
   virtual void Flush();
 
   std::ofstream mOutputFile;
 };
 
+// WARNING: This should not be used in its existing state because
+// it is likely to OOM because of large continguous allocations.
+class DrawEventRecorderMemory final : public DrawEventRecorderPrivate
+{
+public:
+  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderMemory)
+
+  /**
+   * Constructs a DrawEventRecorder that stores the recording in memory.
+   */
+  DrawEventRecorderMemory();
+
+  /**
+   * @return the current size of the recording (in chars).
+   */
+  size_t RecordingSize();
+
+  /**
+   * Copies at most aBufferLen chars of the recording into aBuffer.
+   *
+   * @param aBuffer buffer to receive the recording chars
+   * @param aBufferLen length of aBuffer
+   * @return true if copied successfully
+   */
+  bool CopyRecording(char* aBuffer, size_t aBufferLen);
+
+  /**
+   * Wipes the internal recording buffer, but the recorder does NOT forget which
+   * objects it has recorded. This can be used so that a recording can be copied
+   * and processed in chunks, releasing memory as it goes.
+   */
+  void WipeRecording();
+
+  /**
+   * Gets a readable reference of the underlying stream, reset to the beginning.
+   */
+  std::istream& GetInputStream() {
+    mMemoryStream.seekg(0);
+    return mMemoryStream;
+  }
+
+private:
+  ~DrawEventRecorderMemory() {};
+
+  void Flush() final;
+
+  std::stringstream mMemoryStream;
+};
+
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_DRAWEVENTRECORDER_H_ */
new file mode 100644
--- /dev/null
+++ b/gfx/2d/InlineTranslator.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "InlineTranslator.h"
+
+#include "gfxContext.h"
+#include "nsDeviceContext.h"
+#include "mozilla/gfx/RecordedEvent.h"
+#include "mozilla/gfx/RecordingTypes.h"
+#include "mozilla/UniquePtr.h"
+
+using namespace mozilla::gfx;
+
+namespace mozilla {
+namespace gfx {
+
+InlineTranslator::InlineTranslator(DrawTarget* aDT, Matrix aMatrix)
+{
+  mBaseDT = aDT;
+  mBaseTransform = aMatrix;
+}
+
+bool
+InlineTranslator::TranslateRecording(std::istream& aRecording)
+{
+  uint32_t magicInt;
+  ReadElement(aRecording, magicInt);
+  if (magicInt != mozilla::gfx::kMagicInt) {
+    return false;
+  }
+
+  uint16_t majorRevision;
+  ReadElement(aRecording, majorRevision);
+  if (majorRevision != kMajorRevision) {
+    return false;
+  }
+
+  uint16_t minorRevision;
+  ReadElement(aRecording, minorRevision);
+  if (minorRevision > kMinorRevision) {
+    return false;
+  }
+
+  int32_t eventType;
+  ReadElement(aRecording, eventType);
+  while (aRecording.good()) {
+    UniquePtr<RecordedEvent> recordedEvent(
+      RecordedEvent::LoadEventFromStream(aRecording,
+      static_cast<RecordedEvent::EventType>(eventType)));
+
+    // Make sure that the whole event was read from the stream successfully.
+    if (!aRecording.good() || !recordedEvent) {
+      return false;
+    }
+
+    if (recordedEvent->GetType() == RecordedEvent::SETTRANSFORM) {
+      RecordedSetTransform* event = static_cast<RecordedSetTransform*>(recordedEvent.get());
+      mBaseDT->SetTransform(event->mTransform * mBaseTransform);
+    } else {
+      if (!recordedEvent->PlayEvent(this)) {
+        return false;
+      }
+    }
+
+    ReadElement(aRecording, eventType);
+  }
+
+  return true;
+}
+
+already_AddRefed<DrawTarget>
+InlineTranslator::CreateDrawTarget(ReferencePtr aRefPtr,
+                                  const gfx::IntSize &aSize,
+                                  gfx::SurfaceFormat aFormat)
+{
+  RefPtr<DrawTarget> drawTarget = mBaseDT;
+  return drawTarget.forget();
+}
+
+FontType
+InlineTranslator::GetDesiredFontType()
+{
+  switch (mBaseDT->GetBackendType()) {
+    case BackendType::DIRECT2D:
+      return FontType::DWRITE;
+    case BackendType::CAIRO:
+      return FontType::CAIRO;
+    case BackendType::SKIA:
+      return FontType::SKIA;
+    default:
+      return FontType::CAIRO;
+  }
+}
+
+} // namespace gfx
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/2d/InlineTranslator.h
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layout_InlineTranslator_h
+#define mozilla_layout_InlineTranslator_h
+
+#include <istream>
+
+#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/Filters.h"
+#include "mozilla/gfx/RecordedEvent.h"
+#include "nsRefPtrHashtable.h"
+
+namespace mozilla {
+namespace gfx {
+
+using gfx::Translator;
+using gfx::ReferencePtr;
+using gfx::DrawTarget;
+using gfx::Path;
+using gfx::SourceSurface;
+using gfx::FilterNode;
+using gfx::GradientStops;
+using gfx::ScaledFont;
+using gfx::NativeFontResource;
+
+class InlineTranslator final : public Translator
+{
+public:
+  explicit InlineTranslator(DrawTarget* aDT, Matrix aMatrix);
+
+  bool TranslateRecording(std::istream& aRecording);
+
+  DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) final
+  {
+    return mBaseDT;
+  }
+
+  Path* LookupPath(ReferencePtr aRefPtr) final
+  {
+    Path* result = mPaths.GetWeak(aRefPtr);
+    MOZ_ASSERT(result);
+    return result;
+  }
+
+  SourceSurface* LookupSourceSurface(ReferencePtr aRefPtr) final
+  {
+    SourceSurface* result = mSourceSurfaces.GetWeak(aRefPtr);
+    MOZ_ASSERT(result);
+    return result;
+  }
+
+  FilterNode* LookupFilterNode(ReferencePtr aRefPtr) final
+  {
+    FilterNode* result = mFilterNodes.GetWeak(aRefPtr);
+    MOZ_ASSERT(result);
+    return result;
+  }
+
+  GradientStops* LookupGradientStops(ReferencePtr aRefPtr) final
+  {
+    GradientStops* result =  mGradientStops.GetWeak(aRefPtr);
+    MOZ_ASSERT(result);
+    return result;
+  }
+
+  ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) final
+  {
+    ScaledFont* result = mScaledFonts.GetWeak(aRefPtr);
+    MOZ_ASSERT(result);
+    return result;
+  }
+
+  UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) final
+  {
+    UnscaledFont* result = mUnscaledFonts.GetWeak(aRefPtr);
+    MOZ_ASSERT(result);
+    return result;
+  }
+
+  NativeFontResource* LookupNativeFontResource(uint64_t aKey) final
+  {
+    NativeFontResource* result = mNativeFontResources.GetWeak(aKey);
+    MOZ_ASSERT(result);
+    return result;
+  }
+
+  void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) final { }
+
+  void AddPath(ReferencePtr aRefPtr, Path *aPath) final
+  {
+    mPaths.Put(aRefPtr, aPath);
+  }
+
+  void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface *aSurface) final
+  {
+    mSourceSurfaces.Put(aRefPtr, aSurface);
+  }
+
+  void AddFilterNode(ReferencePtr aRefPtr, FilterNode *aFilter) final
+  {
+    mFilterNodes.Put(aRefPtr, aFilter);
+  }
+
+  void AddGradientStops(ReferencePtr aRefPtr, GradientStops *aStops) final
+  {
+    mGradientStops.Put(aRefPtr, aStops);
+  }
+
+  void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) final
+  {
+    mScaledFonts.Put(aRefPtr, aScaledFont);
+  }
+
+  void AddUnscaledFont(ReferencePtr aRefPtr, UnscaledFont *aUnscaledFont) final
+  {
+    mUnscaledFonts.Put(aRefPtr, aUnscaledFont);
+  }
+
+  void AddNativeFontResource(uint64_t aKey,
+                             NativeFontResource *aScaledFontResouce) final
+  {
+    mNativeFontResources.Put(aKey, aScaledFontResouce);
+  }
+
+  void RemoveDrawTarget(ReferencePtr aRefPtr) final { }
+
+  void RemovePath(ReferencePtr aRefPtr) final
+  {
+    mPaths.Remove(aRefPtr);
+  }
+
+  void RemoveSourceSurface(ReferencePtr aRefPtr) final
+  {
+    mSourceSurfaces.Remove(aRefPtr);
+  }
+
+  void RemoveFilterNode(ReferencePtr aRefPtr) final
+  {
+    mFilterNodes.Remove(aRefPtr);
+  }
+
+  void RemoveGradientStops(ReferencePtr aRefPtr) final
+  {
+    mGradientStops.Remove(aRefPtr);
+  }
+
+  void RemoveScaledFont(ReferencePtr aRefPtr) final
+  {
+    mScaledFonts.Remove(aRefPtr);
+  }
+
+  void RemoveUnscaledFont(ReferencePtr aRefPtr) final
+  {
+    mUnscaledFonts.Remove(aRefPtr);
+  }
+
+
+  already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
+                                                const gfx::IntSize &aSize,
+                                                gfx::SurfaceFormat aFormat) final;
+
+  mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
+
+  mozilla::gfx::FontType GetDesiredFontType() final;
+
+private:
+  RefPtr<DrawTarget> mBaseDT;
+  Matrix             mBaseTransform;
+
+  nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
+  nsRefPtrHashtable<nsPtrHashKey<void>, SourceSurface> mSourceSurfaces;
+  nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
+  nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
+  nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
+  nsRefPtrHashtable<nsPtrHashKey<void>, UnscaledFont> mUnscaledFonts;
+  nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // mozilla_layout_InlineTranslator_h
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -697,22 +697,22 @@ public:
   }
 
   virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "SetTransform"; }
+
+  Matrix mTransform;
 private:
   friend class RecordedEvent;
 
    MOZ_IMPLICIT RecordedSetTransform(std::istream &aStream);
-
-  Matrix mTransform;
 };
 
 class RecordedDrawSurface : public RecordedDrawingEvent {
 public:
   RecordedDrawSurface(DrawTarget *aDT, ReferencePtr aRefSource, const Rect &aDest,
                       const Rect &aSource, const DrawSurfaceOptions &aDSOptions,
                       const DrawOptions &aOptions)
     : RecordedDrawingEvent(DRAWSURFACE, aDT), mRefSource(aRefSource), mDest(aDest)
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -19,21 +19,23 @@ EXPORTS.mozilla.gfx += [
     'BaseSize.h',
     'BezierUtils.h',
     'Blur.h',
     'BorrowedContext.h',
     'Coord.h',
     'CriticalSection.h',
     'DataSurfaceHelpers.h',
     'DrawEventRecorder.h',
+    'DrawTargetRecording.h',
     'DrawTargetTiled.h',
     'Filters.h',
     'FontVariation.h',
     'Helpers.h',
     'HelpersCairo.h',
+    'InlineTranslator.h',
     'IterableArena.h',
     'JobScheduler.h',
     'JobScheduler_posix.h',
     'JobScheduler_win32.h',
     'Logging.h',
     'LoggingConstants.h',
     'Matrix.h',
     'MatrixFwd.h',
@@ -192,16 +194,17 @@ UNIFIED_SOURCES += [
     'SFNTNameTable.cpp',
     'SourceSurfaceCairo.cpp',
     'SourceSurfaceRawData.cpp',
     'Swizzle.cpp',
 ]
 
 SOURCES += [
     'Factory.cpp', # Need to suppress warnings in Skia header files.
+    'InlineTranslator.cpp',
 ]
 
 if CONFIG['CLANG_CXX']:
     SOURCES['Factory.cpp'].flags += ['-Wno-implicit-fallthrough']
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']