Bug 756767 - Part 1: Simplify SourceSurfaceD2D and add DataSourceSurface support. r=jrmuizel
authorBas Schouten <bschouten@mozilla.com>
Mon, 21 May 2012 17:27:30 +0200
changeset 94552 63a4c2f2a0b9611e8f921330936adf63300ca70c
parent 94551 64415d67fc2a34b0ae1d4a1d414ff8bc1e3e4a29
child 94553 bbb12d0bcf4966ee6dfbcc9d42a69a83256bfc12
push id9675
push userbschouten@mozilla.com
push dateTue, 22 May 2012 05:06:08 +0000
treeherdermozilla-inbound@bbb12d0bcf49 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs756767
milestone15.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 756767 - Part 1: Simplify SourceSurfaceD2D and add DataSourceSurface support. r=jrmuizel
gfx/2d/2D.h
gfx/2d/DrawTargetD2D.cpp
gfx/2d/DrawTargetD2D.h
gfx/2d/Factory.cpp
gfx/2d/HelpersD2D.h
gfx/2d/Makefile.in
gfx/2d/SourceSurfaceD2D.cpp
gfx/2d/SourceSurfaceD2D.h
gfx/2d/SourceSurfaceD2DTarget.cpp
gfx/2d/SourceSurfaceD2DTarget.h
gfx/2d/SourceSurfaceRawData.cpp
gfx/2d/SourceSurfaceRawData.h
gfx/2d/Tools.h
gfx/2d/gfx2d.vcxproj
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -306,17 +306,17 @@ public:
   virtual TemporaryRef<DataSourceSurface> GetDataSurface() = 0;
 };
 
 class DataSourceSurface : public SourceSurface
 {
 public:
   virtual SurfaceType GetType() const { return SURFACE_DATA; }
   /* Get the raw bitmap data of the surface */
-  virtual unsigned char *GetData() = 0;
+  virtual uint8_t *GetData() = 0;
   /*
    * Stride of the surface, distance in bytes between the start of the image
    * data belonging to row y and row y+1. This may be negative.
    */
   virtual int32_t Stride() = 0;
 
   /*
    * This function is called after modifying the data on the source surface
@@ -805,25 +805,25 @@ public:
 
   /*
    * This creates a simple data source surface for a certain size. It allocates
    * new memory for the surface. This memory is freed when the surface is
    * destroyed.
    */
   static TemporaryRef<DataSourceSurface>
     CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat);
-  
+
   /*
    * This creates a simple data source surface for some existing data. It will
    * wrap this data and the data for this source surface. The caller is
    * responsible for deallocating the memory only after destruction of the
    * surface.
    */
   static TemporaryRef<DataSourceSurface>
-    CreateDataSourceSurfaceFromData(unsigned char *aData, int32_t aStride,
+    CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
                                     const IntSize &aSize, SurfaceFormat aFormat);
 
 #ifdef WIN32
   static TemporaryRef<DrawTarget> CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
   static TemporaryRef<DrawTarget>
     CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
                                          ID3D10Texture2D *aTextureB,
                                          SurfaceFormat aFormat);
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -253,45 +253,51 @@ DrawTargetD2D::DrawSurface(SourceSurface
   switch (aSurface->GetType()) {
 
   case SURFACE_D2D1_BITMAP:
     {
       SourceSurfaceD2D *srcSurf = static_cast<SourceSurfaceD2D*>(aSurface);
       bitmap = srcSurf->GetBitmap();
 
       if (!bitmap) {
-        if (aSource.width > rt->GetMaximumBitmapSize() ||
-            aSource.height > rt->GetMaximumBitmapSize()) {
-          gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail.";
-          // Don't know how to deal with this yet.
-          return;
-        }
-
-        int stride = srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat());
-
-        unsigned char *data = srcSurf->mRawData +
-                              (uint32_t)aSource.y * stride +
-                              (uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat());
-
-        D2D1_BITMAP_PROPERTIES props =
-          D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat())));
-        mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap));
-
-        srcRect.x -= (uint32_t)aSource.x;
-        srcRect.y -= (uint32_t)aSource.y;
+        return;
       }
     }
     break;
   case SURFACE_D2D1_DRAWTARGET:
     {
       SourceSurfaceD2DTarget *srcSurf = static_cast<SourceSurfaceD2DTarget*>(aSurface);
       bitmap = srcSurf->GetBitmap(mRT);
       AddDependencyOnSource(srcSurf);
     }
     break;
+  case SURFACE_DATA:
+    {
+      DataSourceSurface *srcSurf = static_cast<DataSourceSurface*>(aSurface);
+      if (aSource.width > rt->GetMaximumBitmapSize() ||
+          aSource.height > rt->GetMaximumBitmapSize()) {
+        gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail.";
+        // Don't know how to deal with this yet.
+        return;
+      }
+
+      int stride = srcSurf->Stride();
+
+      unsigned char *data = srcSurf->GetData() +
+                            (uint32_t)aSource.y * stride +
+                            (uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat());
+
+      D2D1_BITMAP_PROPERTIES props =
+        D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat())));
+      mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap));
+
+      srcRect.x -= (uint32_t)aSource.x;
+      srcRect.y -= (uint32_t)aSource.y;
+    }
+    break;
   }
 
   rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect));
 
   FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), aDest);
 }
 
 void
@@ -1975,32 +1981,39 @@ DrawTargetD2D::CreateBrushForPattern(con
     switch (pat->mSurface->GetType()) {
     case SURFACE_D2D1_BITMAP:
       {
         SourceSurfaceD2D *surf = static_cast<SourceSurfaceD2D*>(pat->mSurface.get());
 
         bitmap = surf->mBitmap;
 
         if (!bitmap) {
-          bitmap = CreatePartialBitmapForSurface(surf, mat);
-
-          if (!bitmap) {
-            return NULL;
-          }
+          return NULL;
         }
       }
       break;
     case SURFACE_D2D1_DRAWTARGET:
       {
         SourceSurfaceD2DTarget *surf =
           static_cast<SourceSurfaceD2DTarget*>(pat->mSurface.get());
         bitmap = surf->GetBitmap(mRT);
         AddDependencyOnSource(surf);
       }
       break;
+    case SURFACE_DATA:
+      {
+        DataSourceSurface *dataSurf =
+          static_cast<DataSourceSurface*>(pat->mSurface.get());
+        bitmap = CreatePartialBitmapForSurface(dataSurf, mat);
+        
+        if (!bitmap) {
+          return NULL;
+        }
+      }
+      break;
     }
     
     mRT->CreateBitmapBrush(bitmap,
                            D2D1::BitmapBrushProperties(D2DExtend(pat->mExtendMode),
                                                        D2DExtend(pat->mExtendMode),
                                                        D2DFilter(pat->mFilter)),
                            D2D1::BrushProperties(aAlpha, D2DMatrix(mat)),
                            byRef(bmBrush));
@@ -2212,17 +2225,17 @@ DrawTargetD2D::CreateTextureForAnalysis(
 
   if (FAILED(hr)) {
     return NULL;
   }
 
   return tex;
 }
 TemporaryRef<ID2D1Bitmap>
-DrawTargetD2D::CreatePartialBitmapForSurface(SourceSurfaceD2D *aSurface, Matrix &aMatrix)
+DrawTargetD2D::CreatePartialBitmapForSurface(DataSourceSurface *aSurface, Matrix &aMatrix)
 {
   RefPtr<ID2D1Bitmap> bitmap;
 
   // This is where things get complicated. The source surface was
   // created for a surface that was too large to fit in a texture.
   // We'll need to figure out if we can work with a partial upload
   // or downsample in software.
 
@@ -2234,62 +2247,63 @@ DrawTargetD2D::CreatePartialBitmapForSur
   }
 
   Rect rect(0, 0, mSize.width, mSize.height);
 
   // Calculate the rectangle of the source mapped to our surface.
   rect = invTransform.TransformBounds(rect);
   rect.RoundOut();
 
-  Rect uploadRect(0, 0, aSurface->mSize.width, aSurface->mSize.height);
+  IntSize size = aSurface->GetSize();
+
+  Rect uploadRect(0, 0, size.width, size.height);
 
   // Calculate the rectangle on the source bitmap that touches our
   // surface.
   uploadRect = uploadRect.Intersect(rect);
 
   if (uploadRect.IsEmpty()) {
     // This bitmap does not cover anything on the screen. XXX -
     // we need to deal with EXTEND modes here!
     return NULL;
   }
 
+  int stride = aSurface->Stride();
+
   if (uploadRect.width <= mRT->GetMaximumBitmapSize() &&
       uploadRect.height <= mRT->GetMaximumBitmapSize()) {
             
-    int Bpp = BytesPerPixel(aSurface->mFormat);
-    int stride = Bpp * aSurface->mSize.width;
+    int Bpp = BytesPerPixel(aSurface->GetFormat());
 
     // A partial upload will suffice.
     mRT->CreateBitmap(D2D1::SizeU(uint32_t(uploadRect.width), uint32_t(uploadRect.height)),
-                      aSurface->mRawData + int(uploadRect.x) * 4 + int(uploadRect.y) * stride,
+                      aSurface->GetData() + int(uploadRect.x) * 4 + int(uploadRect.y) * stride,
                       stride,
-                      D2D1::BitmapProperties(D2DPixelFormat(aSurface->mFormat)),
+                      D2D1::BitmapProperties(D2DPixelFormat(aSurface->GetFormat())),
                       byRef(bitmap));
 
     aMatrix.Translate(uploadRect.x, uploadRect.y);
 
     return bitmap;
   } else {
-    int Bpp = BytesPerPixel(aSurface->mFormat);
+    int Bpp = BytesPerPixel(aSurface->GetFormat());
 
     if (Bpp != 4) {
       // This shouldn't actually happen in practice!
       MOZ_ASSERT(false);
       return NULL;
     }
 
-    int stride = Bpp * aSurface->mSize.width;
-
-    ImageHalfScaler scaler(aSurface->mRawData, stride, IntSize(aSurface->mSize));
+    ImageHalfScaler scaler(aSurface->GetData(), stride, size);
 
     // Calculate the maximum width/height of the image post transform.
-    Point topRight = transform * Point(aSurface->mSize.width, 0);
+    Point topRight = transform * Point(size.width, 0);
     Point topLeft = transform * Point(0, 0);
-    Point bottomRight = transform * Point(aSurface->mSize.width, aSurface->mSize.height);
-    Point bottomLeft = transform * Point(0, aSurface->mSize.height);
+    Point bottomRight = transform * Point(size.width, size.height);
+    Point bottomLeft = transform * Point(0, size.height);
     
     IntSize scaleSize;
 
     scaleSize.width = max(Distance(topRight, topLeft), Distance(bottomRight, bottomLeft));
     scaleSize.height = max(Distance(topRight, bottomRight), Distance(topLeft, bottomLeft));
 
     if (scaleSize.width > mRT->GetMaximumBitmapSize()) {
       // Ok, in this case we'd really want a downscale of a part of the bitmap,
@@ -2302,20 +2316,20 @@ DrawTargetD2D::CreatePartialBitmapForSur
     }
 
     scaler.ScaleForSize(scaleSize);
 
     IntSize newSize = scaler.GetSize();
     
     mRT->CreateBitmap(D2D1::SizeU(newSize.width, newSize.height),
                       scaler.GetScaledData(), scaler.GetStride(),
-                      D2D1::BitmapProperties(D2DPixelFormat(aSurface->mFormat)),
+                      D2D1::BitmapProperties(D2DPixelFormat(aSurface->GetFormat())),
                       byRef(bitmap));
 
-    aMatrix.Scale(aSurface->mSize.width / newSize.width, aSurface->mSize.height / newSize.height);
+    aMatrix.Scale(size.width / newSize.width, size.height / newSize.height);
     return bitmap;
   }
 }
 
 void
 DrawTargetD2D::SetupEffectForRadialGradient(const RadialGradientPattern *aPattern)
 {
   mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->GetPassByIndex(0)->Apply(0);
--- a/gfx/2d/DrawTargetD2D.h
+++ b/gfx/2d/DrawTargetD2D.h
@@ -175,20 +175,20 @@ private:
   TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
   TemporaryRef<ID2D1Geometry> GetClippedGeometry();
 
   TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
 
   TemporaryRef<ID3D10Texture2D> CreateGradientTexture(const GradientStopsD2D *aStops);
   TemporaryRef<ID3D10Texture2D> CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds);
 
-  // This creates a partially uploaded bitmap for a SourceSurfaceD2D that is
-  // too big to fit in a bitmap. It adjusts the passed Matrix to accomodate the
-  // partial upload.
-  TemporaryRef<ID2D1Bitmap> CreatePartialBitmapForSurface(SourceSurfaceD2D *aSurface, Matrix &aMatrix);
+  // This creates a (partially) uploaded bitmap for a DataSourceSurface. It
+  // uploads the minimum requirement and possibly downscales. It adjusts the
+  // input Matrix to compensate.
+  TemporaryRef<ID2D1Bitmap> CreatePartialBitmapForSurface(DataSourceSurface *aSurface, Matrix &aMatrix);
 
   void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern);
   void SetupStateForRendering();
 
   static const uint32_t test = 4;
 
   IntSize mSize;
 
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -32,16 +32,18 @@
 #ifdef WIN32
 #include "DrawTargetD2D.h"
 #include "ScaledFontDWrite.h"
 #include <d3d10_1.h>
 #endif
 
 #include "DrawTargetDual.h"
 
+#include "SourceSurfaceRawData.h"
+
 #include "Logging.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo *sGFX2DLog = PR_NewLogModule("gfx2d");
 #endif
 
 // The following code was largely taken from xpcom/glue/SSE.cpp and
 // made a little simpler.
@@ -356,10 +358,24 @@ Factory::CreateDrawTargetForCairoSurface
   if (newTarget->Init(aSurface)) {
     return newTarget;
   }
 
 #endif
   return NULL;
 }
 
+TemporaryRef<DataSourceSurface>
+Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
+                                         const IntSize &aSize,
+                                         SurfaceFormat aFormat)
+{
+  RefPtr<SourceSurfaceRawData> newSurf = new SourceSurfaceRawData();
+
+  if (newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false)) {
+    return newSurf;
+  }
+
+  return NULL;
+}
+
 }
 }
--- a/gfx/2d/HelpersD2D.h
+++ b/gfx/2d/HelpersD2D.h
@@ -127,26 +127,16 @@ static inline D2D1_ALPHA_MODE AlphaMode(
   return D2D1_ALPHA_MODE_PREMULTIPLIED;
 }
 
 static inline D2D1_PIXEL_FORMAT D2DPixelFormat(SurfaceFormat aFormat)
 {
   return D2D1::PixelFormat(DXGIFormat(aFormat), AlphaMode(aFormat));
 }
 
-static inline int BytesPerPixel(SurfaceFormat aFormat)
-{
-  switch (aFormat) {
-  case FORMAT_A8:
-    return 1;
-  default:
-    return 4;
-  }
-}
-
 static bool IsPatternSupportedByD2D(const Pattern &aPattern)
 {
   if (aPattern.GetType() != PATTERN_RADIAL_GRADIENT) {
     return false;
   }
 
   const RadialGradientPattern *pat =
     static_cast<const RadialGradientPattern*>(&aPattern);
--- a/gfx/2d/Makefile.in
+++ b/gfx/2d/Makefile.in
@@ -38,16 +38,17 @@ CPPSRCS	= \
         Matrix.cpp \
         DrawTargetCairo.cpp \
         SourceSurfaceCairo.cpp \
         PathCairo.cpp \
         Blur.cpp \
         ScaledFontBase.cpp \
         DrawTargetDual.cpp \
         ImageScaling.cpp \
+        SourceSurfaceRawData.cpp \
         $(NULL)
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS	+= \
 	   SourceSurfaceCG.cpp \
 	   DrawTargetCG.cpp \
 	   PathCG.cpp \
 	   $(NULL)
--- a/gfx/2d/SourceSurfaceD2D.cpp
+++ b/gfx/2d/SourceSurfaceD2D.cpp
@@ -5,23 +5,21 @@
 
 #include "SourceSurfaceD2D.h"
 #include "Logging.h"
 
 namespace mozilla {
 namespace gfx {
 
 SourceSurfaceD2D::SourceSurfaceD2D()
-  : mRawData(NULL)
 {
 }
 
 SourceSurfaceD2D::~SourceSurfaceD2D()
 {
-  delete [] mRawData;
 }
 
 IntSize
 SourceSurfaceD2D::GetSize() const
 {
   return mSize;
 }
 
@@ -46,25 +44,18 @@ SourceSurfaceD2D::InitFromData(unsigned 
 {
   HRESULT hr;
 
   mFormat = aFormat;
   mSize = aSize;
 
   if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
       (uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
-    int newStride = BytesPerPixel(aFormat) * aSize.width;
-    // This should only be called once!
-    MOZ_ASSERT(!mRawData);
-    mRawData = new uint8_t[aSize.height * newStride];
-    for (int y = 0; y < aSize.height; y++) {
-      memcpy(mRawData + y * newStride, aData + y * aStride, newStride);
-    }
-    gfxDebug() << "Bitmap does not fit in texture, saving raw data.";
-    return true;
+    gfxDebug() << "Bitmap does not fit in texture.";
+    return false;
   }
 
   D2D1_BITMAP_PROPERTIES props =
     D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(aFormat), AlphaMode(aFormat)));
   hr = aRT->CreateBitmap(D2DIntSize(aSize), aData, aStride, props, byRef(mBitmap));
 
   if (FAILED(hr)) {
     gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hr;
--- a/gfx/2d/SourceSurfaceD2D.h
+++ b/gfx/2d/SourceSurfaceD2D.h
@@ -34,17 +34,16 @@ public:
   bool InitFromTexture(ID3D10Texture2D *aTexture,
                        SurfaceFormat aFormat,
                        ID2D1RenderTarget *aRT);
 
 private:
   friend class DrawTargetD2D;
 
   RefPtr<ID2D1Bitmap> mBitmap;
-  uint8_t *mRawData;
   SurfaceFormat mFormat;
   IntSize mSize;
 };
 
 }
 }
 
 #endif /* MOZILLA_GFX_SOURCESURFACED2D_H_ */
--- a/gfx/2d/SourceSurfaceD2DTarget.cpp
+++ b/gfx/2d/SourceSurfaceD2DTarget.cpp
@@ -203,17 +203,17 @@ DataSourceSurfaceD2DTarget::GetSize() co
 }
 
 SurfaceFormat
 DataSourceSurfaceD2DTarget::GetFormat() const
 {
   return mFormat;
 }
 
-unsigned char*
+uint8_t*
 DataSourceSurfaceD2DTarget::GetData()
 {
   EnsureMapped();
 
   return (unsigned char*)mMap.pData;
 }
 
 int32_t
--- a/gfx/2d/SourceSurfaceD2DTarget.h
+++ b/gfx/2d/SourceSurfaceD2DTarget.h
@@ -58,17 +58,17 @@ class DataSourceSurfaceD2DTarget : publi
 {
 public:
   DataSourceSurfaceD2DTarget();
   ~DataSourceSurfaceD2DTarget();
 
   virtual SurfaceType GetType() const { return SURFACE_DATA; }
   virtual IntSize GetSize() const;
   virtual SurfaceFormat GetFormat() const;
-  virtual unsigned char *GetData();
+  virtual uint8_t *GetData();
   virtual int32_t Stride();
 
 private:
   friend class SourceSurfaceD2DTarget;
   void EnsureMapped();
 
   mutable RefPtr<ID3D10Texture2D> mTexture;
   SurfaceFormat mFormat;
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceRawData.cpp
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 "SourceSurfaceRawData.h"
+#include "Logging.h"
+#include "Tools.h"
+
+namespace mozilla {
+namespace gfx {
+
+bool
+SourceSurfaceRawData::InitWrappingData(uint8_t *aData,
+                                       const IntSize &aSize,
+                                       int32_t aStride,
+                                       SurfaceFormat aFormat,
+                                       bool aOwnData)
+{
+  mRawData = aData;
+  mSize = aSize;
+  mStride = aStride;
+  mFormat = aFormat;
+  mOwnData = aOwnData;
+
+  return true;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceRawData.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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_GFX_SOURCESURFACERAWDATA_H_
+#define MOZILLA_GFX_SOURCESURFACERAWDATA_H_
+
+#include "2D.h"
+
+namespace mozilla {
+namespace gfx {
+
+class SourceSurfaceRawData : public DataSourceSurface
+{
+public:
+  SourceSurfaceRawData() {}
+  ~SourceSurfaceRawData() { if(mOwnData) delete [] mRawData; }
+
+  virtual uint8_t *GetData() { return mRawData; }
+  virtual int32_t Stride() { return mStride; }
+
+  virtual SurfaceType GetType() const { return SURFACE_DATA; }
+  virtual IntSize GetSize() const { return mSize; }
+  virtual SurfaceFormat GetFormat() const { return mFormat; }
+
+  bool InitWrappingData(unsigned char *aData,
+                        const IntSize &aSize,
+                        int32_t aStride,
+                        SurfaceFormat aFormat,
+                        bool aOwnData);
+
+private:
+  uint8_t *mRawData;
+  int32_t mStride;
+  SurfaceFormat mFormat;
+  IntSize mSize;
+  bool mOwnData;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_SOURCESURFACERAWDATA_H_ */
--- a/gfx/2d/Tools.h
+++ b/gfx/2d/Tools.h
@@ -47,12 +47,25 @@ FuzzyEqual(Float aA, Float aB, Float aEr
 }
 
 static inline Float
 Distance(Point aA, Point aB)
 {
   return hypotf(aB.x - aA.x, aB.y - aA.y);
 }
 
+static inline int
+BytesPerPixel(SurfaceFormat aFormat)
+{
+  switch (aFormat) {
+  case FORMAT_A8:
+    return 1;
+  case FORMAT_R5G6B5:
+    return 2;
+  default:
+    return 4;
+  }
+}
+
 }
 }
 
 #endif /* MOZILLA_GFX_TOOLS_H_ */
--- a/gfx/2d/gfx2d.vcxproj
+++ b/gfx/2d/gfx2d.vcxproj
@@ -1,119 +1,121 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <Keyword>Win32Proj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <ExecutablePath>$(DXSDK_DIR)\Utilities\bin\x86;$(ExecutablePath)</ExecutablePath>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PreprocessorDefinitions>USE_SSE2;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);GFX_LOG_DEBUG;GFX_LOG_WARNING;MFBT_STAND_ALONE;XP_WIN</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <Optimization>Disabled</Optimization>
-    </ClCompile>
-    <Link>
-      <TargetMachine>MachineX86</TargetMachine>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Windows</SubSystem>
-      <EntryPointSymbol>
-      </EntryPointSymbol>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PreprocessorDefinitions>USE_SSE2;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <Link>
-      <TargetMachine>MachineX86</TargetMachine>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Windows</SubSystem>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClInclude Include="2D.h" />
-    <ClInclude Include="BaseMargin.h" />
-    <ClInclude Include="BasePoint.h" />
-    <ClInclude Include="BaseRect.h" />
-    <ClInclude Include="BaseSize.h" />
-    <ClInclude Include="DrawTargetD2D.h" />
-    <ClInclude Include="DrawTargetDual.h" />
-    <ClInclude Include="GradientStopsD2D.h" />
-    <ClInclude Include="HelpersD2D.h" />
-    <ClInclude Include="ImageScaling.h" />
-    <ClInclude Include="Logging.h" />
-    <ClInclude Include="Matrix.h" />
-    <ClInclude Include="PathD2D.h" />
-    <ClInclude Include="Point.h" />
-    <ClInclude Include="Rect.h" />
-    <ClInclude Include="ScaledFontDWrite.h" />
-    <ClInclude Include="SourceSurfaceD2D.h" />
-    <ClInclude Include="SourceSurfaceD2DTarget.h" />
-    <ClInclude Include="Tools.h" />
-    <ClInclude Include="Types.h" />
-    <ClInclude Include="UserData.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="DrawTargetD2D.cpp" />
-    <ClCompile Include="DrawTargetDual.cpp" />
-    <ClCompile Include="Factory.cpp" />
-    <ClCompile Include="ImageScaling.cpp" />
-    <ClCompile Include="ImageScalingSSE2.cpp" />
-    <ClCompile Include="Matrix.cpp" />
-    <ClCompile Include="PathD2D.cpp" />
-    <ClCompile Include="ScaledFontDWrite.cpp" />
-    <ClCompile Include="SourceSurfaceD2D.cpp" />
-    <ClCompile Include="SourceSurfaceD2DTarget.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="Makefile.in" />
-    <CustomBuild Include="ShadersD2D.fx">
-      <FileType>Document</FileType>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">fxc /Tfx_4_0 /FhShadersD2D.h ShadersD2D.fx /Vn d2deffect</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">ShadersD2D.h</Outputs>
-    </CustomBuild>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <ExecutablePath>$(DXSDK_DIR)\Utilities\bin\x86;$(ExecutablePath)</ExecutablePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>USE_SSE2;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);GFX_LOG_DEBUG;GFX_LOG_WARNING;MFBT_STAND_ALONE;XP_WIN</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EntryPointSymbol>
+      </EntryPointSymbol>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>USE_SSE2;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="2D.h" />
+    <ClInclude Include="BaseMargin.h" />
+    <ClInclude Include="BasePoint.h" />
+    <ClInclude Include="BaseRect.h" />
+    <ClInclude Include="BaseSize.h" />
+    <ClInclude Include="DrawTargetD2D.h" />
+    <ClInclude Include="DrawTargetDual.h" />
+    <ClInclude Include="GradientStopsD2D.h" />
+    <ClInclude Include="HelpersD2D.h" />
+    <ClInclude Include="ImageScaling.h" />
+    <ClInclude Include="Logging.h" />
+    <ClInclude Include="Matrix.h" />
+    <ClInclude Include="PathD2D.h" />
+    <ClInclude Include="Point.h" />
+    <ClInclude Include="Rect.h" />
+    <ClInclude Include="ScaledFontDWrite.h" />
+    <ClInclude Include="SourceSurfaceD2D.h" />
+    <ClInclude Include="SourceSurfaceD2DTarget.h" />
+    <ClInclude Include="SourceSurfaceRawData.h" />
+    <ClInclude Include="Tools.h" />
+    <ClInclude Include="Types.h" />
+    <ClInclude Include="UserData.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="DrawTargetD2D.cpp" />
+    <ClCompile Include="DrawTargetDual.cpp" />
+    <ClCompile Include="Factory.cpp" />
+    <ClCompile Include="ImageScaling.cpp" />
+    <ClCompile Include="ImageScalingSSE2.cpp" />
+    <ClCompile Include="Matrix.cpp" />
+    <ClCompile Include="PathD2D.cpp" />
+    <ClCompile Include="ScaledFontDWrite.cpp" />
+    <ClCompile Include="SourceSurfaceD2D.cpp" />
+    <ClCompile Include="SourceSurfaceD2DTarget.cpp" />
+    <ClCompile Include="SourceSurfaceRawData.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Makefile.in" />
+    <CustomBuild Include="ShadersD2D.fx">
+      <FileType>Document</FileType>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">fxc /Tfx_4_0 /FhShadersD2D.h ShadersD2D.fx /Vn d2deffect</Command>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">ShadersD2D.h</Outputs>
+    </CustomBuild>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
 </Project>
\ No newline at end of file