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 209860 0a69bc9e746c57bde3eba792c9bec6eef7245f25
parent 209859 c61c91ea40fe9c5d74eff210505faec01867eda8
child 209861 b7f4185d9a8e05640c05e300f2d9c4f93c1826f2
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjrmuizel
bugs1078693
milestone35.0a1
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();