Bug 1078693: Correctly indicate validity of a SourceSurfaceD2D1 and deal with failed surface creation. r=jrmuizel
authorBas Schouten <bschouten@mozilla.com>
Fri, 10 Oct 2014 17:04:26 +0200
changeset 233075 0a69bc9e746c57bde3eba792c9bec6eef7245f25
parent 233074 c61c91ea40fe9c5d74eff210505faec01867eda8
child 233076 b7f4185d9a8e05640c05e300f2d9c4f93c1826f2
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1078693
milestone35.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 1078693: Correctly indicate validity of a SourceSurfaceD2D1 and deal with failed surface creation. r=jrmuizel
gfx/2d/SourceSurfaceD2D1.cpp
gfx/2d/SourceSurfaceD2D1.h
--- a/gfx/2d/SourceSurfaceD2D1.cpp
+++ b/gfx/2d/SourceSurfaceD2D1.cpp
@@ -11,45 +11,66 @@ namespace mozilla {
 namespace gfx {
 
 SourceSurfaceD2D1::SourceSurfaceD2D1(ID2D1Image *aImage, ID2D1DeviceContext *aDC,
                                      SurfaceFormat aFormat, const IntSize &aSize,
                                      DrawTargetD2D1 *aDT)
   : mImage(aImage)
   , mDC(aDC)
   , mDrawTarget(aDT)
+  , mDevice(Factory::GetD2D1Device())
 {
   aImage->QueryInterface((ID2D1Bitmap1**)byRef(mRealizedBitmap));
 
   mFormat = aFormat;
   mSize = aSize;
 }
 
 SourceSurfaceD2D1::~SourceSurfaceD2D1()
 {
 }
 
+bool
+SourceSurfaceD2D1::IsValid() const
+{
+  return mDevice == Factory::GetD2D1Device();
+}
+
 TemporaryRef<DataSourceSurface>
 SourceSurfaceD2D1::GetDataSurface()
 {
+  HRESULT hr;
+
   EnsureRealizedBitmap();
 
   RefPtr<ID2D1Bitmap1> softwareBitmap;
   D2D1_BITMAP_PROPERTIES1 props;
   props.dpiX = 96;
   props.dpiY = 96;
   props.pixelFormat = D2DPixelFormat(mFormat);
   props.colorContext = nullptr;
   props.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW |
                         D2D1_BITMAP_OPTIONS_CPU_READ;
-  mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(softwareBitmap));
+  hr = mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(softwareBitmap));
+
+  if (FAILED(hr)) {
+    gfxCriticalError() << "Failed to create software bitmap: " << mSize << " Code: " << hexa(hr);
+    return nullptr;
+  }
 
   D2D1_POINT_2U point = D2D1::Point2U(0, 0);
   D2D1_RECT_U rect = D2D1::RectU(0, 0, mSize.width, mSize.height);
-  softwareBitmap->CopyFromBitmap(&point, mRealizedBitmap, &rect);
+  
+  hr = softwareBitmap->CopyFromBitmap(&point, mRealizedBitmap, &rect);
+
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to readback into software bitmap. Code: " << hexa(hr);
+    return nullptr;
+  }
+
   return new DataSourceSurfaceD2D1(softwareBitmap, mFormat);
 }
 
 void
 SourceSurfaceD2D1::EnsureRealizedBitmap()
 {
   if (mRealizedBitmap) {
     return;
--- a/gfx/2d/SourceSurfaceD2D1.h
+++ b/gfx/2d/SourceSurfaceD2D1.h
@@ -24,16 +24,17 @@ public:
   SourceSurfaceD2D1(ID2D1Image* aImage, ID2D1DeviceContext *aDC,
                     SurfaceFormat aFormat, const IntSize &aSize,
                     DrawTargetD2D1 *aDT = nullptr);
   ~SourceSurfaceD2D1();
 
   virtual SurfaceType GetType() const { return SurfaceType::D2D1_1_IMAGE; }
   virtual IntSize GetSize() const { return mSize; }
   virtual SurfaceFormat GetFormat() const { return mFormat; }
+  virtual bool IsValid() const;
   virtual TemporaryRef<DataSourceSurface> GetDataSurface();
 
   ID2D1Image *GetImage() { return mImage; }
 
   void EnsureIndependent() { if (!mDrawTarget) return; DrawTargetWillChange(); }
 
 private:
   friend class DrawTargetD2D1;
@@ -49,32 +50,35 @@ private:
   // this may happen on destruction or copying.
   void MarkIndependent();
 
   RefPtr<ID2D1Image> mImage;
   // This may be null if we were created for a non-bitmap image and have not
   // had a reason yet to realize ourselves.
   RefPtr<ID2D1Bitmap1> mRealizedBitmap;
   RefPtr<ID2D1DeviceContext> mDC;
+  // Keep this around to verify whether out image is still valid in the future.
+  RefPtr<ID2D1Device> mDevice;
 
   SurfaceFormat mFormat;
   IntSize mSize;
   DrawTargetD2D1* mDrawTarget;
 };
 
 class DataSourceSurfaceD2D1 : public DataSourceSurface
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2D1)
   DataSourceSurfaceD2D1(ID2D1Bitmap1 *aMappableBitmap, SurfaceFormat aFormat);
   ~DataSourceSurfaceD2D1();
 
   virtual SurfaceType GetType() const { return SurfaceType::DATA; }
   virtual IntSize GetSize() const;
   virtual SurfaceFormat GetFormat() const { return mFormat; }
+  virtual bool IsValid() const { return !!mBitmap; }
   virtual uint8_t *GetData();
   virtual int32_t Stride();
   virtual bool Map(MapType, MappedSurface *aMappedSurface);
   virtual void Unmap();
 
 private:
   friend class SourceSurfaceD2DTarget;
   void EnsureMapped();