Bug 1299164: Part 2. Use BufferSizeFromDimensions method, as well as some of the others that check for valid size. r=bas
authorMilan Sreckovic <milan@mozilla.com>
Thu, 15 Sep 2016 10:36:21 -0400
changeset 355385 1aecdb3b9974b17b11f503310a2e35e1e730f04a
parent 355384 e2d722f565d3e63b7cee7772b2f79d32482363f8
child 355386 af84ff6bfd7ec84ba6670bd76e49d0c4b01f43de
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1299164
milestone51.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 1299164: Part 2. Use BufferSizeFromDimensions method, as well as some of the others that check for valid size. r=bas
dom/base/ImageEncoder.cpp
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/ImageBitmapRenderingContext.cpp
dom/plugins/ipc/PluginInstanceChild.cpp
gfx/2d/Factory.cpp
gfx/2d/ImageScaling.cpp
gfx/2d/SourceSurfaceRawData.h
gfx/layers/TextureDIB.cpp
gfx/layers/basic/GrallocTextureHostBasic.cpp
gfx/layers/composite/CanvasLayerComposite.cpp
gfx/layers/composite/ImageLayerComposite.cpp
gfx/thebes/gfxAndroidPlatform.cpp
gfx/thebes/gfxPlatformGtk.cpp
gfx/thebes/gfxPlatformMac.cpp
gfx/thebes/gfxWindowsPlatform.cpp
--- a/dom/base/ImageEncoder.cpp
+++ b/dom/base/ImageEncoder.cpp
@@ -364,16 +364,20 @@ ImageEncoder::ExtractDataInternal(const 
     return NS_ERROR_INVALID_ARG;
   }
 
   nsCOMPtr<nsIInputStream> imgStream;
 
   // get image bytes
   nsresult rv;
   if (aImageBuffer) {
+    if (BufferSizeFromDimensions(aSize.width, aSize.height, 4) == 0) {
+      return NS_ERROR_INVALID_ARG;
+    }
+
     rv = ImageEncoder::GetInputStream(
       aSize.width,
       aSize.height,
       aImageBuffer,
       aFormat,
       aEncoder,
       nsPromiseFlatString(aOptions).get(),
       getter_AddRefs(imgStream));
@@ -412,16 +416,20 @@ ImageEncoder::ExtractDataInternal(const 
       rv = aEncoder->InitFromData(data.Elements(),
                                   aSize.width * aSize.height * 4,
                                   aSize.width,
                                   aSize.height,
                                   aSize.width * 4,
                                   imgIEncoder::INPUT_FORMAT_HOSTARGB,
                                   aOptions);
     } else {
+      if (BufferSizeFromDimensions(aSize.width, aSize.height, 4) == 0) {
+        return NS_ERROR_INVALID_ARG;
+      }
+
       RefPtr<gfx::DataSourceSurface> dataSurface;
       RefPtr<layers::Image> image(aImage);
       dataSurface = GetBRGADataSourceSurfaceSync(image.forget());
 
       DataSourceSurface::MappedSurface map;
       if (!dataSurface->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
         return NS_ERROR_INVALID_ARG;
       }
@@ -434,22 +442,20 @@ ImageEncoder::ExtractDataInternal(const 
                                   aOptions);
       dataSurface->Unmap();
     }
 
     if (NS_SUCCEEDED(rv)) {
       imgStream = do_QueryInterface(aEncoder);
     }
   } else {
-    CheckedInt32 requiredBytes = CheckedInt32(aSize.width) * CheckedInt32(aSize.height) * 4;
-    if (MOZ_UNLIKELY(!requiredBytes.isValid())) {
+    if (BufferSizeFromDimensions(aSize.width, aSize.height, 4) == 0) {
       return NS_ERROR_INVALID_ARG;
     }
 
-
     // no context, so we have to encode an empty image
     // note that if we didn't have a current context, the spec says we're
     // supposed to just return transparent black pixels of the canvas
     // dimensions.
     RefPtr<DataSourceSurface> emptyCanvas =
       Factory::CreateDataSourceSurfaceWithStride(IntSize(aSize.width, aSize.height),
                                                  SurfaceFormat::B8G8R8A8,
                                                  4 * aSize.width, true);
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5244,18 +5244,23 @@ CanvasRenderingContext2D::DrawWindow(nsG
       (!mBufferProvider || mBufferProvider->GetType() != LayersBackend::LAYERS_CLIENT))
   {
     thebes = gfxContext::CreateOrNull(mTarget);
     MOZ_ASSERT(thebes); // already checked the draw target above
                         // (in SupportsAzureContentForDrawTarget)
     thebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21,
                                 matrix._22, matrix._31, matrix._32));
   } else {
+    IntSize dtSize = IntSize::Ceil(sw, sh);
+    if (!Factory::AllowedSurfaceSize(dtSize)) {
+      aError.Throw(NS_ERROR_FAILURE);
+      return;
+    }
     drawDT =
-      gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize::Ceil(sw, sh),
+      gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(dtSize,
                                                                    SurfaceFormat::B8G8R8A8);
     if (!drawDT || !drawDT->IsValid()) {
       aError.Throw(NS_ERROR_FAILURE);
       return;
     }
 
     thebes = gfxContext::CreateOrNull(drawDT);
     MOZ_ASSERT(thebes); // alrady checked the draw target above
@@ -5271,16 +5276,22 @@ CanvasRenderingContext2D::DrawWindow(nsG
 
   if (drawDT) {
     RefPtr<SourceSurface> snapshot = drawDT->Snapshot();
     if (NS_WARN_IF(!snapshot)) {
       aError.Throw(NS_ERROR_FAILURE);
       return;
     }
     RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
+    if (!data || !Factory::AllowedSurfaceSize(data->GetSize())) {
+      gfxCriticalError() << "Unexpected invalid data source surface " <<
+        (data ? data->GetSize() : IntSize(0,0));
+      aError.Throw(NS_ERROR_FAILURE);
+      return;
+    }
 
     DataSourceSurface::MappedSurface rawData;
     if (NS_WARN_IF(!data->Map(DataSourceSurface::READ, &rawData))) {
         aError.Throw(NS_ERROR_FAILURE);
         return;
     }
     RefPtr<SourceSurface> source =
       mTarget->CreateSourceSurfaceFromData(rawData.mData,
--- a/dom/canvas/ImageBitmapRenderingContext.cpp
+++ b/dom/canvas/ImageBitmapRenderingContext.cpp
@@ -104,17 +104,18 @@ ImageBitmapRenderingContext::MatchWithIn
   }
 
   RefPtr<DrawTarget> dt =
     Factory::CreateDrawTargetForData(BackendType::CAIRO,
                                      map.GetData(),
                                      temp->GetSize(),
                                      map.GetStride(),
                                      temp->GetFormat());
-  if (!dt) {
+  if (!dt || !dt->IsValid()) {
+    gfxWarning() << "ImageBitmapRenderingContext::MatchWithIntrinsicSize failed";
     return nullptr;
   }
 
 
   dt->ClearRect(Rect(0, 0, mWidth, mHeight));
   dt->CopySurface(surface,
                   IntRect(0, 0, surface->GetSize().width,
                                 surface->GetSize().height),
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -3791,19 +3791,23 @@ PluginInstanceChild::PaintRectToSurface(
                                               imageSurface->Data(),
                                               imageSurface->GetSize(),
                                               imageSurface->Stride(),
                                               SurfaceFormat::B8G8R8A8);
       } else {
         // Copy helper surface content to target
         dt = CreateDrawTargetForSurface(aSurface);
       }
-      RefPtr<SourceSurface> surface =
-        gfxPlatform::GetSourceSurfaceForSurface(dt, renderSurface);
-      dt->CopySurface(surface, aRect, aRect.TopLeft());
+      if (dt && dt->IsValid()) {
+          RefPtr<SourceSurface> surface =
+              gfxPlatform::GetSourceSurfaceForSurface(dt, renderSurface);
+          dt->CopySurface(surface, aRect, aRect.TopLeft());
+      } else {
+          gfxWarning() << "PluginInstanceChild::PaintRectToSurface failure";
+      }
     }
 }
 
 void
 PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
                                                   gfxASurface* aSurface)
 {
     MOZ_ASSERT(aSurface->GetContentType() == gfxContentType::COLOR_ALPHA,
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -731,16 +731,20 @@ Factory::CreateDrawTargetSkiaWithGrConte
 void
 Factory::PurgeAllCaches()
 {
 }
 
 already_AddRefed<DrawTarget>
 Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat)
 {
+  if (!AllowedSurfaceSize(aSize)) {
+    gfxWarning() << "Allowing surface with invalid size (Cairo) " << aSize;
+  }
+
   RefPtr<DrawTarget> retVal;
 
 #ifdef USE_CAIRO
   RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo();
 
   if (newTarget->Init(aSurface, aSize, aFormat)) {
     retVal = newTarget;
   }
@@ -766,16 +770,21 @@ Factory::CreateSourceSurfaceForCairoSurf
   return nullptr;
 #endif
 }
 
 #ifdef XP_DARWIN
 already_AddRefed<DrawTarget>
 Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize)
 {
+  if (!AllowedSurfaceSize(aSize)) {
+    gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (CG) " << aSize;
+    return nullptr;
+  }
+
   RefPtr<DrawTarget> retVal;
 
   RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
 
   if (newTarget->Init(cg, aSize)) {
     retVal = newTarget;
   }
 
@@ -795,17 +804,17 @@ Factory::CreateCGGlyphRenderingOptions(c
 already_AddRefed<DataSourceSurface>
 Factory::CreateWrappingDataSourceSurface(uint8_t *aData,
                                          int32_t aStride,
                                          const IntSize &aSize,
                                          SurfaceFormat aFormat,
                                          SourceSurfaceDeallocator aDeallocator /* = nullptr */,
                                          void* aClosure /* = nullptr */)
 {
-  if (aSize.width <= 0 || aSize.height <= 0) {
+  if (!AllowedSurfaceSize(aSize)) {
     return nullptr;
   }
   if (!aDeallocator && aClosure) {
     return nullptr;
   }
 
   MOZ_ASSERT(aData);
 
@@ -839,17 +848,18 @@ Factory::CreateDataSourceSurface(const I
 }
 
 already_AddRefed<DataSourceSurface>
 Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize,
                                            SurfaceFormat aFormat,
                                            int32_t aStride,
                                            bool aZero)
 {
-  if (aStride < aSize.width * BytesPerPixel(aFormat)) {
+  if (!AllowedSurfaceSize(aSize) ||
+      aStride < aSize.width * BytesPerPixel(aFormat)) {
     gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "CreateDataSourceSurfaceWithStride failed with bad stride " << aStride << ", " << aSize << ", " << aFormat;
     return nullptr;
   }
 
   // Skia doesn't support RGBX, so memset RGBX to 0xFF
   bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8;
   uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0;
 
--- a/gfx/2d/ImageScaling.cpp
+++ b/gfx/2d/ImageScaling.cpp
@@ -60,30 +60,30 @@ ImageHalfScaler::ScaleForSize(const IntS
     horizontalDownscales++;
     scaleSize.width /= 2;
   }
 
   if (scaleSize == mOrigSize) {
     return;
   }
 
+  delete [] mDataStorage;
+
   IntSize internalSurfSize;
-
   internalSurfSize.width = max(scaleSize.width, mOrigSize.width / 2);
   internalSurfSize.height = max(scaleSize.height, mOrigSize.height / 2);
 
-  mStride = internalSurfSize.width * 4;
-  if (mStride % 16) {
-    mStride += 16 - (mStride % 16);
+  size_t bufLen = 0;
+  mStride = GetAlignedStride<16>(internalSurfSize.width, 4);
+  if (mStride > 0) {
+    // Allocate 15 bytes extra to make sure we can get 16 byte alignment. We
+    // should add tools for this, see bug 751696.
+    bufLen = BufferSizeFromStrideAndHeight(mStride, internalSurfSize.height, 15);
   }
 
-  delete [] mDataStorage;
-  // Allocate 15 bytes extra to make sure we can get 16 byte alignment. We
-  // should add tools for this, see bug 751696.
-  size_t bufLen = BufferSizeFromStrideAndHeight(mStride, internalSurfSize.height, 15);
   if (bufLen == 0) {
     mSize.SizeTo(0, 0);
     mDataStorage = nullptr;
     return;
   }
   mDataStorage = new uint8_t[bufLen];
 
   if (uintptr_t(mDataStorage) % 16) {
--- a/gfx/2d/SourceSurfaceRawData.h
+++ b/gfx/2d/SourceSurfaceRawData.h
@@ -75,17 +75,18 @@ public:
     mMapCount--;
     MOZ_ASSERT(mMapCount >= 0);
   }
 
 private:
   friend class Factory;
 
   // If we have a custom deallocator, the |aData| will be released using the
-  // custom deallocator and |aClosure| in dtor.
+  // custom deallocator and |aClosure| in dtor.  The assumption is that the
+  // caller will check for valid size and stride before making this call.
   void InitWrappingData(unsigned char *aData,
                         const IntSize &aSize,
                         int32_t aStride,
                         SurfaceFormat aFormat,
                         Factory::SourceSurfaceDeallocator aDeallocator,
                         void* aClosure);
 
   uint8_t *mRawData;
--- a/gfx/layers/TextureDIB.cpp
+++ b/gfx/layers/TextureDIB.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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 "TextureDIB.h"
 #include "gfx2DGlue.h"
+#include "mozilla/gfx/DataSurfaceHelpers.h" // For BufferSizeFromDimensions
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
@@ -428,17 +429,17 @@ DIBTextureHost::UpdatedInternal(const ns
       gfxWarning() << "Bad Cairo surface internal update " << mSurface->CairoStatus();
       mTextureSource = nullptr;
       return;
   }
   RefPtr<gfxImageSurface> imgSurf = mSurface->GetAsImageSurface();
 
   RefPtr<DataSourceSurface> surf = Factory::CreateWrappingDataSourceSurface(imgSurf->Data(), imgSurf->Stride(), mSize, mFormat);
 
-  if (!mTextureSource->Update(surf, const_cast<nsIntRegion*>(aRegion))) {
+  if (!surf || !mTextureSource->Update(surf, const_cast<nsIntRegion*>(aRegion))) {
     mTextureSource = nullptr;
   }
 
   ReadUnlock();
 }
 
 TextureHostFileMapping::TextureHostFileMapping(TextureFlags aFlags,
                                                const SurfaceDescriptorFileMapping& aDescriptor)
@@ -468,24 +469,30 @@ TextureHostFileMapping::UpdatedInternal(
     // attached to a layer.
     return;
   }
 
   if (!mTextureSource) {
     mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
   }
 
-  uint8_t* data = (uint8_t*)::MapViewOfFile(mFileMapping, FILE_MAP_READ, 0, 0, mSize.width * mSize.height * BytesPerPixel(mFormat));
+  uint8_t* data = nullptr;
+  int32_t totalBytes = BufferSizeFromDimensions(mSize.width, mSize.height, BytesPerPixel(mFormat));
+  if (totalBytes > 0) {
+    data = (uint8_t*)::MapViewOfFile(mFileMapping, FILE_MAP_READ, 0, 0, totalBytes);
+  }
 
   if (data) {
     RefPtr<DataSourceSurface> surf = Factory::CreateWrappingDataSourceSurface(data, mSize.width * BytesPerPixel(mFormat), mSize, mFormat);
-
-    surf->AddUserData(&kFileMappingKey, data, UnmapFileData);
-
-    if (!mTextureSource->Update(surf, const_cast<nsIntRegion*>(aRegion))) {
+    if (surf) {
+        surf->AddUserData(&kFileMappingKey, data, UnmapFileData);
+        if (!mTextureSource->Update(surf, const_cast<nsIntRegion*>(aRegion))) {
+          mTextureSource = nullptr;
+        }
+    } else {
       mTextureSource = nullptr;
     }
   } else {
     mTextureSource = nullptr;
   }
 
   ReadUnlock();
 }
--- a/gfx/layers/basic/GrallocTextureHostBasic.cpp
+++ b/gfx/layers/basic/GrallocTextureHostBasic.cpp
@@ -135,19 +135,23 @@ GrallocTextureHostBasic::Lock()
       return false;
     }
     surf = gfx::Factory::CreateWrappingDataSourceSurface(
              mMappedBuffer,
              graphicBuffer->getStride() * gfx::BytesPerPixel(mFormat),
              mCropSize,
              mFormat);
   }
-  mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
-  mTextureSource->Update(surf, nullptr);
-  return true;
+  if (surf) {
+    mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
+    mTextureSource->Update(surf, nullptr);
+    return true;
+  }
+  mMappedBuffer = nullptr;
+  return false;
 }
 
 bool
 GrallocTextureHostBasic::IsValid() const
 {
   android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
   return graphicBuffer != nullptr;
 }
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -84,17 +84,19 @@ CanvasLayerComposite::RenderLayer(const 
     return;
   }
 
   mCompositor->MakeCurrent();
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxEnv::DumpCompositorTextures()) {
     RefPtr<gfx::DataSourceSurface> surf = mCompositableHost->GetAsSurface();
-    WriteSnapshotToDumpFile(this, surf);
+    if (surf) {
+      WriteSnapshotToDumpFile(this, surf);
+    }
   }
 #endif
 
   RenderWithAllMasks(this, mCompositor, aClipRect,
                      [&](EffectChain& effectChain, const IntRect& clipRect) {
     mCompositableHost->Composite(this, effectChain,
                           GetEffectiveOpacity(),
                           GetEffectiveTransform(),
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -94,17 +94,19 @@ ImageLayerComposite::RenderLayer(const I
 {
   if (!mImageHost || !mImageHost->IsAttached()) {
     return;
   }
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxEnv::DumpCompositorTextures()) {
     RefPtr<gfx::DataSourceSurface> surf = mImageHost->GetAsSurface();
-    WriteSnapshotToDumpFile(this, surf);
+    if (surf) {
+      WriteSnapshotToDumpFile(this, surf);
+    }
   }
 #endif
 
   mCompositor->MakeCurrent();
 
   RenderWithAllMasks(this, mCompositor, aClipRect,
                      [&](EffectChain& effectChain, const IntRect& clipRect) {
     mImageHost->SetCompositor(mCompositor);
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -118,16 +118,20 @@ gfxAndroidPlatform::~gfxAndroidPlatform(
     FT_Done_Library(gPlatformFTLibrary);
     gPlatformFTLibrary = nullptr;
 }
 
 already_AddRefed<gfxASurface>
 gfxAndroidPlatform::CreateOffscreenSurface(const IntSize& aSize,
                                            gfxImageFormat aFormat)
 {
+    if (!Factory::AllowedSurfaceSize(aSize)) {
+        return nullptr;
+    }
+
     RefPtr<gfxASurface> newSurface;
     newSurface = new gfxImageSurface(aSize, aFormat);
 
     return newSurface.forget();
 }
 
 static bool
 IsJapaneseLocale()
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -137,16 +137,20 @@ gfxPlatformGtk::FlushContentDrawing()
         XFlush(DefaultXDisplay());
     }
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformGtk::CreateOffscreenSurface(const IntSize& aSize,
                                        gfxImageFormat aFormat)
 {
+    if (!Factory::AllowedSurfaceSize(aSize)) {
+        return nullptr;
+    }
+
     RefPtr<gfxASurface> newSurface;
     bool needsClear = true;
 #ifdef MOZ_X11
     // XXX we really need a different interface here, something that passes
     // in more context, including the display and/or target surface type that
     // we should try to match
     GdkScreen *gdkScreen = gdk_screen_get_default();
     if (gdkScreen) {
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -111,16 +111,20 @@ gfxPlatformMac::CreatePlatformFontList()
     gfxPlatformFontList::Shutdown();
     return nullptr;
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformMac::CreateOffscreenSurface(const IntSize& aSize,
                                        gfxImageFormat aFormat)
 {
+    if (!Factory::AllowedSurfaceSize(aSize)) {
+        return nullptr;
+    }
+
     RefPtr<gfxASurface> newSurface =
       new gfxQuartzSurface(aSize, aFormat);
     return newSurface.forget();
 }
 
 already_AddRefed<ScaledFont>
 gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -580,16 +580,20 @@ gfxWindowsPlatform::DisableD2D(FeatureSt
   Factory::SetDirect3D11Device(nullptr);
   UpdateBackendPrefs();
 }
 
 already_AddRefed<gfxASurface>
 gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& aSize,
                                            gfxImageFormat aFormat)
 {
+    if (!Factory::AllowedSurfaceSize(aSize)) {
+        return nullptr;
+    }
+
     RefPtr<gfxASurface> surf = nullptr;
 
 #ifdef CAIRO_HAS_WIN32_SURFACE
     if (mRenderMode == RENDER_GDI || mRenderMode == RENDER_DIRECT2D)
         surf = new gfxWindowsSurface(aSize, aFormat);
 #endif
 
     if (!surf || surf->CairoStatus()) {