Bug 605057 - Add gfxASurface::GetAsImageSurface to convert generic surfaces into image surfaces without copies (if possible). r=roc a=b
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 11 Nov 2010 15:31:22 -0500
changeset 57344 44a537c00ab68322f54f42cd182e683cb2bc2af1
parent 57343 9bbe81c91524e35fa6d18d2dda57bbe68b45dd59
child 57345 42244cff985a141c3a8401f92264ddd6939e9e6d
push id16887
push userjdrew@mozilla.com
push dateThu, 11 Nov 2010 20:37:00 +0000
treeherdermozilla-central@182eb3c4fc44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, b
bugs605057
milestone2.0b8pre
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 605057 - Add gfxASurface::GetAsImageSurface to convert generic surfaces into image surfaces without copies (if possible). r=roc a=b
gfx/layers/d3d9/CanvasLayerD3D9.cpp
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/thebes/GLContextProviderWGL.cpp
gfx/thebes/gfxASurface.h
gfx/thebes/gfxDDrawSurface.cpp
gfx/thebes/gfxDDrawSurface.h
gfx/thebes/gfxImageSurface.cpp
gfx/thebes/gfxImageSurface.h
gfx/thebes/gfxQPainterSurface.cpp
gfx/thebes/gfxQPainterSurface.h
gfx/thebes/gfxQuartzImageSurface.cpp
gfx/thebes/gfxQuartzImageSurface.h
gfx/thebes/gfxWindowsNativeDrawing.cpp
gfx/thebes/gfxWindowsSurface.cpp
gfx/thebes/gfxWindowsSurface.h
modules/libpr0n/src/imgFrame.cpp
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -178,17 +178,17 @@ CanvasLayerD3D9::Updated(const nsIntRect
     }
 
     PRUint8 *startBits;
     PRUint32 sourceStride;
 
     nsRefPtr<gfxImageSurface> sourceSurface;
 
     if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
-      sourceSurface = static_cast<gfxWindowsSurface*>(mSurface.get())->GetImageSurface();
+      sourceSurface = mSurface->GetAsImageSurface();
       startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
                   aRect.x * 4;
       sourceStride = sourceSurface->Stride();
     } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
       sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
       if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
           sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
       {
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -155,17 +155,17 @@ CanvasLayerOGL::Updated(const nsIntRect&
     }
 
     nsRefPtr<gfxImageSurface> updatedAreaImageSurface;
     if (mCanvasSurface) {
       nsRefPtr<gfxASurface> sourceSurface = mCanvasSurface;
 
 #ifdef XP_WIN
       if (sourceSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
-        sourceSurface = static_cast<gfxWindowsSurface*>(sourceSurface.get())->GetImageSurface();
+        sourceSurface = sourceSurface->GetAsImageSurface();
         if (!sourceSurface)
           sourceSurface = mCanvasSurface;
       }
 #endif
 
 #if 0
       // XXX don't copy, blah.
       // but need to deal with stride on the gl side; do this later.
--- a/gfx/thebes/GLContextProviderWGL.cpp
+++ b/gfx/thebes/GLContextProviderWGL.cpp
@@ -463,18 +463,17 @@ protected:
     }
 
     virtual already_AddRefed<gfxImageSurface>
     GetImageForUpload(gfxASurface* aUpdateSurface)
     {
         nsRefPtr<gfxImageSurface> uploadImage;
 
         if (aUpdateSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
-            gfxWindowsSurface* ws = static_cast<gfxWindowsSurface*>(aUpdateSurface);
-            uploadImage = ws->GetImageSurface();
+            uploadImage = aUpdateSurface->GetAsImageSurface();
         } else {
             uploadImage = new gfxImageSurface(mUpdateSize, mUpdateFormat);
             nsRefPtr<gfxContext> cx(new gfxContext(uploadImage));
             cx->SetSource(aUpdateSurface);
             cx->SetOperator(gfxContext::OPERATOR_SOURCE);
             cx->Paint();
         }
 
--- a/gfx/thebes/gfxASurface.h
+++ b/gfx/thebes/gfxASurface.h
@@ -145,16 +145,27 @@ public:
 
     /**
      * Create an offscreen surface that can be efficiently copied into
      * this surface (at least if tiling is not involved).
      * Returns null on error.
      */
     virtual already_AddRefed<gfxASurface> CreateSimilarSurface(gfxContentType aType,
                                                                const gfxIntSize& aSize);
+
+    /**
+     * Returns an image surface for this surface, or nsnull if not supported.
+     * This will not copy image data, just wraps an image surface around
+     * pixel data already available in memory.
+     */
+    virtual already_AddRefed<gfxImageSurface> GetAsImageSurface()
+    {
+      return nsnull;
+    }
+
     /**
      * Return trues if offscreen surfaces created from this surface
      * would behave differently depending on the gfxContentType. Returns
      * false if they don't (i.e. the surface returned by
      * CreateOffscreenSurface is always as if you passed
      * CONTENT_COLOR_ALPHA). Knowing this can be useful to avoid
      * recreating a surface just because it changed from opaque to
      * transparent.
--- a/gfx/thebes/gfxDDrawSurface.cpp
+++ b/gfx/thebes/gfxDDrawSurface.cpp
@@ -74,17 +74,17 @@ gfxDDrawSurface::~gfxDDrawSurface()
 }
 
 LPDIRECTDRAWSURFACE gfxDDrawSurface::GetDDSurface()
 {
     return cairo_ddraw_surface_get_ddraw_surface(CairoSurface());
 }
 
 already_AddRefed<gfxImageSurface>
-gfxDDrawSurface::GetImageSurface()
+gfxDDrawSurface::GetAsImageSurface()
 {
     cairo_surface_t *isurf = cairo_ddraw_surface_get_image(CairoSurface());
     if (!isurf)
         return nsnull;
 
     nsRefPtr<gfxASurface> asurf = gfxASurface::Wrap(isurf);
     gfxImageSurface *imgsurf = (gfxImageSurface*) asurf.get();
     NS_ADDREF(imgsurf);
--- a/gfx/thebes/gfxDDrawSurface.h
+++ b/gfx/thebes/gfxDDrawSurface.h
@@ -52,17 +52,17 @@ public:
     gfxDDrawSurface(gfxDDrawSurface * psurf, const RECT & rect);
 
     gfxDDrawSurface(cairo_surface_t *csurf);
 
     LPDIRECTDRAWSURFACE GetDDSurface();
 
     virtual ~gfxDDrawSurface();
 
-    already_AddRefed<gfxImageSurface> gfxDDrawSurface::GetImageSurface();
+    already_AddRefed<gfxImageSurface> GetAsImageSurface();
 
     nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
     nsresult EndPrinting();
     nsresult AbortPrinting();
     nsresult BeginPage();
     nsresult EndPage();
 
     virtual PRInt32 GetDefaultContextFlags() const;
--- a/gfx/thebes/gfxImageSurface.cpp
+++ b/gfx/thebes/gfxImageSurface.cpp
@@ -219,8 +219,15 @@ gfxImageSurface::GetSubimage(const gfxRe
 
 gfxSubimageSurface::gfxSubimageSurface(gfxImageSurface* aParent,
                                        unsigned char* aData,
                                        const gfxIntSize& aSize)
   : gfxImageSurface(aData, aSize, aParent->Stride(), aParent->Format())
   , mParent(aParent)
 {
 }
+
+already_AddRefed<gfxImageSurface>
+gfxImageSurface::GetAsImageSurface()
+{
+  nsRefPtr<gfxImageSurface> surface = this;
+  return surface.forget();
+}
--- a/gfx/thebes/gfxImageSurface.h
+++ b/gfx/thebes/gfxImageSurface.h
@@ -101,16 +101,18 @@ public:
     /* Fast copy from another image surface; returns TRUE if successful, FALSE otherwise */
     PRBool CopyFrom (gfxImageSurface *other);
 
     /* return new Subimage with pointing to original image starting from aRect.pos
      * and size of aRect.size. New subimage keeping current image reference
      */
     already_AddRefed<gfxSubimageSurface> GetSubimage(const gfxRect& aRect);
 
+    virtual already_AddRefed<gfxImageSurface> GetAsImageSurface();
+
 protected:
     gfxImageSurface();
     void InitWithData(unsigned char *aData, const gfxIntSize& aSize,
                       long aStride, gfxImageFormat aFormat);
     void InitFromSurface(cairo_surface_t *csurf);
     long ComputeStride() const;
 
     gfxIntSize mSize;
--- a/gfx/thebes/gfxQPainterSurface.cpp
+++ b/gfx/thebes/gfxQPainterSurface.cpp
@@ -89,17 +89,17 @@ gfxQPainterSurface::GetQImage()
 {
     if (!mSurfaceValid)
         return nsnull;
 
     return cairo_qt_surface_get_qimage(CairoSurface());
 }
 
 already_AddRefed<gfxImageSurface>
-gfxQPainterSurface::GetImageSurface()
+gfxQPainterSurface::GetAsImageSurface()
 {
     if (!mSurfaceValid)
         return nsnull;
 
     cairo_surface_t *isurf = cairo_qt_surface_get_image(CairoSurface());
     if (!isurf)
         return nsnull;
 
--- a/gfx/thebes/gfxQPainterSurface.h
+++ b/gfx/thebes/gfxQPainterSurface.h
@@ -55,17 +55,17 @@ public:
 
     gfxQPainterSurface(cairo_surface_t *csurf);
 
     virtual ~gfxQPainterSurface();
 
     QPainter *GetQPainter() { return mPainter; }
 
     QImage *GetQImage();
-    already_AddRefed<gfxImageSurface> GetImageSurface();
+    already_AddRefed<gfxImageSurface> GetAsImageSurface();
 
 protected:
     QPainter *mPainter;
 };
 
 #endif
 
 #endif /* GFX_QPAINTERSURFACE_H */
--- a/gfx/thebes/gfxQuartzImageSurface.cpp
+++ b/gfx/thebes/gfxQuartzImageSurface.cpp
@@ -54,17 +54,17 @@ gfxQuartzImageSurface::gfxQuartzImageSur
     Init (csurf, PR_TRUE);
 }
 
 gfxQuartzImageSurface::~gfxQuartzImageSurface()
 {
 }
 
 already_AddRefed<gfxImageSurface>
-gfxQuartzImageSurface::GetImageSurface()
+gfxQuartzImageSurface::GetAsImageSurface()
 {
     if (!mSurfaceValid)
         return nsnull;
 
     cairo_surface_t *isurf = cairo_quartz_image_surface_get_image (CairoSurface());
     if (!isurf) {
         NS_WARNING ("Couldn't obtain an image surface from a QuartzImageSurface?!");
         return nsnull;
--- a/gfx/thebes/gfxQuartzImageSurface.h
+++ b/gfx/thebes/gfxQuartzImageSurface.h
@@ -43,12 +43,12 @@
 
 class THEBES_API gfxQuartzImageSurface : public gfxASurface {
 public:
     gfxQuartzImageSurface(gfxImageSurface *imageSurface);
     gfxQuartzImageSurface(cairo_surface_t *csurf);
 
     virtual ~gfxQuartzImageSurface();
 
-    already_AddRefed<gfxImageSurface> GetImageSurface();
+    already_AddRefed<gfxImageSurface> GetAsImageSurface();
 };
 
 #endif /* GFX_QUARTZIMAGESURFACE_H */
--- a/gfx/thebes/gfxWindowsNativeDrawing.cpp
+++ b/gfx/thebes/gfxWindowsNativeDrawing.cpp
@@ -277,18 +277,18 @@ gfxWindowsNativeDrawing::EndNativeDrawin
 
 void
 gfxWindowsNativeDrawing::PaintToContext()
 {
     if (mRenderState == RENDER_STATE_NATIVE_DRAWING_DONE) {
         // nothing to do, it already went to the context
         mRenderState = RENDER_STATE_DONE;
     } else if (mRenderState == RENDER_STATE_ALPHA_RECOVERY_WHITE_DONE) {
-        nsRefPtr<gfxImageSurface> black = mBlackSurface->GetImageSurface();
-        nsRefPtr<gfxImageSurface> white = mWhiteSurface->GetImageSurface();
+        nsRefPtr<gfxImageSurface> black = mBlackSurface->GetAsImageSurface();
+        nsRefPtr<gfxImageSurface> white = mWhiteSurface->GetAsImageSurface();
         if (!gfxAlphaRecovery::RecoverAlpha(black, white)) {
             NS_ERROR("Alpha recovery failure");
             return;
         }
         nsRefPtr<gfxImageSurface> alphaSurface =
             new gfxImageSurface(black->Data(), black->GetSize(),
                                 black->Stride(),
                                 gfxASurface::ImageFormatARGB32);
--- a/gfx/thebes/gfxWindowsSurface.cpp
+++ b/gfx/thebes/gfxWindowsSurface.cpp
@@ -142,17 +142,17 @@ gfxWindowsSurface::~gfxWindowsSurface()
 
 HDC
 gfxWindowsSurface::GetDCWithClip(gfxContext *ctx)
 {
     return cairo_win32_get_dc_with_clip (ctx->GetCairo());
 }
 
 already_AddRefed<gfxImageSurface>
-gfxWindowsSurface::GetImageSurface()
+gfxWindowsSurface::GetAsImageSurface()
 {
     if (!mSurfaceValid) {
         NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
         return nsnull;
     }
 
     NS_ASSERTION(CairoSurface() != nsnull, "CairoSurface() shouldn't be nsnull when mSurfaceValid is TRUE!");
 
--- a/gfx/thebes/gfxWindowsSurface.h
+++ b/gfx/thebes/gfxWindowsSurface.h
@@ -70,17 +70,17 @@ public:
     void InitWithDC(PRUint32 flags);
 
     virtual ~gfxWindowsSurface();
 
     HDC GetDC() { return mDC; }
 
     HDC GetDCWithClip(gfxContext *);
 
-    already_AddRefed<gfxImageSurface> GetImageSurface();
+    already_AddRefed<gfxImageSurface> GetAsImageSurface();
 
     already_AddRefed<gfxWindowsSurface> OptimizeToDDB(HDC dc,
                                                       const gfxIntSize& size,
                                                       gfxImageFormat format);
 
     virtual TextQuality GetTextQualityInTransparentSurfaces()
     {
       return TEXT_QUALITY_OK_OVER_OPAQUE_PIXELS;
--- a/modules/libpr0n/src/imgFrame.cpp
+++ b/modules/libpr0n/src/imgFrame.cpp
@@ -212,17 +212,17 @@ nsresult imgFrame::Init(PRInt32 aX, PRIn
     // For Windows, we must create the device surface first (if we're
     // going to) so that the image surface can wrap it.  Can't be done
     // the other way around.
 #ifdef USE_WIN_SURFACE
     if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) {
       mWinSurface = new gfxWindowsSurface(gfxIntSize(mSize.width, mSize.height), mFormat);
       if (mWinSurface && mWinSurface->CairoStatus() == 0) {
         // no error
-        mImageSurface = mWinSurface->GetImageSurface();
+        mImageSurface = mWinSurface->GetAsImageSurface();
       } else {
         mWinSurface = nsnull;
       }
     }
 #endif
 
     // For other platforms we create the image surface first and then
     // possibly wrap it in a device surface.  This branch is also used