Bug 651858 - Part 2: Add glue code in gfx for thebes-azure interop. r=jrmuizel
authorBas Schouten <bschouten@mozilla.com>
Fri, 24 Jun 2011 19:41:18 +0200
changeset 71714 95039cfae6a3d88fe0b906e97c9657f4557d38c4
parent 71713 4ede291d2e4c9dff7e75c2062db29e62f8e81984
child 71715 0f674a8c14a3c93a218c43920b3065d75b1f2139
push id20601
push usermak77@bonardo.net
push dateSat, 25 Jun 2011 10:05:20 +0000
treeherdermozilla-central@48ad4ffc4230 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs651858
milestone7.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 651858 - Part 2: Add glue code in gfx for thebes-azure interop. r=jrmuizel
gfx/cairo/cairo/src/cairo-d2d-surface.cpp
gfx/cairo/cairo/src/cairo-win32.h
gfx/thebes/Makefile.in
gfx/thebes/gfx2DGlue.h
gfx/thebes/gfxD2DSurface.cpp
gfx/thebes/gfxD2DSurface.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -4598,16 +4598,31 @@ cairo_d2d_surface_create_for_texture(cai
     return reinterpret_cast<cairo_surface_t*>(newSurf);
 
 FAIL_CREATE:
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
 }
 
+ID3D10Texture2D*
+cairo_d2d_surface_get_texture(cairo_surface_t *surface)
+{
+    if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
+        return NULL;
+    }
+
+    cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
+
+    RefPtr<ID3D10Texture2D> texture;
+    d2dsurf->surface->QueryInterface(&texture);
+
+    return texture;
+}
+
 void cairo_d2d_scroll(cairo_surface_t *surface, int x, int y, cairo_rectangle_t *clip)
 {
     if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
 	return;
     }
     cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
 
     /** For now, we invalidate our storing texture with this operation. */
--- a/gfx/cairo/cairo/src/cairo-win32.h
+++ b/gfx/cairo/cairo/src/cairo-win32.h
@@ -246,16 +246,21 @@ cairo_d2d_surface_create_for_handle(cair
  * \return New cairo surface
  */
 cairo_public cairo_surface_t *
 cairo_d2d_surface_create_for_texture(cairo_device_t *device,
 				     struct ID3D10Texture2D *texture,
 				     cairo_content_t content);
 
 /**
+ * Get the ID3D10Texture2D used for a surface.
+ */
+cairo_public struct ID3D10Texture2D *cairo_d2d_surface_get_texture(cairo_surface_t *surf);
+
+/**
  * Present the backbuffer for a surface create for an HWND. This needs
  * to be called when the owner of the original window surface wants to
  * actually present the executed drawing operations to the screen.
  *
  * \param surface D2D surface.
  */
 void cairo_d2d_present_backbuffer(cairo_surface_t *surface);
 
--- a/gfx/thebes/Makefile.in
+++ b/gfx/thebes/Makefile.in
@@ -7,16 +7,17 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= thebes
 LIBRARY_NAME	= thebes
 LIBXUL_LIBRARY	= 1
 EXPORT_LIBRARY	= 1
 
 EXPORTS	= \
+        gfx2DGlue.h \
 	gfx3DMatrix.h \
 	gfxASurface.h \
 	gfxAlphaRecovery.h \
 	gfxBlur.h \
 	gfxCachedTempSurface.h \
 	gfxColor.h \
 	gfxContext.h \
 	gfxDrawable.h \
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/gfx2DGlue.h
@@ -0,0 +1,40 @@
+
+#include "gfxRect.h"
+#include "mozilla/gfx/Rect.h"
+
+namespace mozilla {
+namespace gfx {
+class DrawTarget;
+class SourceSurface;
+class ScaledFont;
+}
+}
+
+namespace mozilla {
+namespace gfx {
+
+inline Rect ToRect(const gfxRect &aRect)
+{
+  return Rect(Float(aRect.x), Float(aRect.y),
+              Float(aRect.width), Float(aRect.height));
+}
+
+inline gfxRect GFXRect(const Rect &aRect)
+{
+  return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
+}
+
+inline gfxASurface::gfxContentType ContentForFormat(const SurfaceFormat &aFormat)
+{
+  switch (aFormat) {
+  case FORMAT_B8G8R8X8:
+    return gfxASurface::CONTENT_COLOR;
+  case FORMAT_A8:
+    return gfxASurface::CONTENT_ALPHA;
+  default:
+    return gfxASurface::CONTENT_COLOR_ALPHA;
+  }
+}
+
+}
+}
--- a/gfx/thebes/gfxD2DSurface.cpp
+++ b/gfx/thebes/gfxD2DSurface.cpp
@@ -92,16 +92,22 @@ gfxD2DSurface::Scroll(const nsIntPoint &
     cairo_rectangle_t rect;
     rect.x = aClip.x;
     rect.y = aClip.y;
     rect.width = aClip.width;
     rect.height = aClip.height;
     cairo_d2d_scroll(CairoSurface(), aDelta.x, aDelta.y, &rect);
 }
 
+ID3D10Texture2D*
+gfxD2DSurface::GetTexture()
+{
+  return cairo_d2d_surface_get_texture(CairoSurface());
+}
+
 HDC
 gfxD2DSurface::GetDC(PRBool aRetainContents)
 {
     return cairo_d2d_get_dc(CairoSurface(), aRetainContents);
 }
 
 void
 gfxD2DSurface::ReleaseDC(const nsIntRect *aUpdatedRect)
--- a/gfx/thebes/gfxD2DSurface.h
+++ b/gfx/thebes/gfxD2DSurface.h
@@ -65,13 +65,15 @@ public:
         FastMovePixels(aSourceRect, aDestTopLeft);
     }
 
     virtual ~gfxD2DSurface();
 
     void Present();
     void Scroll(const nsIntPoint &aDelta, const nsIntRect &aClip);
 
+    ID3D10Texture2D *GetTexture();
+
     HDC GetDC(PRBool aRetainContents);
     void ReleaseDC(const nsIntRect *aUpdatedRect);
 };
 
 #endif /* GFX_D2DSURFACE_H */
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -39,16 +39,17 @@
 #define FORCE_PR_LOG /* Allow logging in the release build */
 #endif
 #include "prlog.h"
 
 #include "gfxPlatform.h"
 
 #if defined(XP_WIN)
 #include "gfxWindowsPlatform.h"
+#include "gfxD2DSurface.h"
 #elif defined(XP_MACOSX)
 #include "gfxPlatformMac.h"
 #elif defined(MOZ_WIDGET_GTK2)
 #include "gfxPlatformGtk.h"
 #elif defined(MOZ_WIDGET_QT)
 #include "gfxQtPlatform.h"
 #elif defined(XP_OS2)
 #include "gfxOS2Platform.h"
@@ -109,16 +110,18 @@ static const char *CMPrefName = "gfx.col
 static const char *CMPrefNameOld = "gfx.color_management.enabled";
 static const char *CMIntentPrefName = "gfx.color_management.rendering_intent";
 static const char *CMProfilePrefName = "gfx.color_management.display_profile";
 static const char *CMForceSRGBPrefName = "gfx.color_management.force_srgb";
 
 static void ShutdownCMS();
 static void MigratePrefs();
 
+#include "mozilla/gfx/2D.h"
+using namespace mozilla::gfx;
 
 // logs shared across gfx
 #ifdef PR_LOGGING
 static PRLogModuleInfo *sFontlistLog = nsnull;
 static PRLogModuleInfo *sFontInitLog = nsnull;
 static PRLogModuleInfo *sTextrunLog = nsnull;
 static PRLogModuleInfo *sTextrunuiLog = nsnull;
 #endif
@@ -410,16 +413,111 @@ gfxPlatform::OptimizeImage(gfxImageSurfa
     tmpCtx.SetSource(aSurface);
     tmpCtx.Paint();
 
     gfxASurface *ret = optSurface;
     NS_ADDREF(ret);
     return ret;
 }
 
+cairo_user_data_key_t kDrawTarget;
+
+RefPtr<DrawTarget>
+gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface)
+{
+#ifdef XP_WIN
+  if (aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
+    RefPtr<DrawTarget> drawTarget =
+      Factory::CreateDrawTargetForD3D10Texture(static_cast<gfxD2DSurface*>(aSurface)->GetTexture(), FORMAT_B8G8R8A8);
+    aSurface->SetData(&kDrawTarget, drawTarget, NULL);
+    return drawTarget;
+  }
+#endif
+
+  // Can't create a draw target for general cairo surfaces yet.
+  return NULL;
+}
+
+cairo_user_data_key_t kSourceSurface;
+
+void SourceBufferDestroy(void *srcBuffer)
+{
+  static_cast<SourceSurface*>(srcBuffer)->Release();
+}
+
+RefPtr<SourceSurface>
+gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
+{
+  void *userData = aSurface->GetData(&kSourceSurface);
+
+  if (userData) {
+    return static_cast<SourceSurface*>(userData);
+  }
+
+  SurfaceFormat format;
+  if (aSurface->GetContentType() == gfxASurface::CONTENT_ALPHA) {
+    format = FORMAT_A8;
+  } else if (aSurface->GetContentType() == gfxASurface::CONTENT_COLOR) {
+    format = FORMAT_B8G8R8X8;
+  } else {
+    format = FORMAT_B8G8R8A8;
+  }
+
+  RefPtr<SourceSurface> srcBuffer;
+
+#ifdef XP_WIN
+  if (aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
+    NativeSurface surf;
+    surf.mFormat = format;
+    surf.mType = NATIVE_SURFACE_D3D10_TEXTURE;
+    surf.mSurface = static_cast<gfxD2DSurface*>(aSurface)->GetTexture();
+    mozilla::gfx::DrawTarget *dt = static_cast<mozilla::gfx::DrawTarget*>(aSurface->GetData(&kDrawTarget));
+    if (dt) {
+      dt->Flush();
+    }
+    srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
+  }
+#endif
+
+  if (!srcBuffer) {
+    nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
+
+    if (!imgSurface) {
+      imgSurface = new gfxImageSurface(aSurface->GetSize(), gfxASurface::FormatFromContent(aSurface->GetContentType()));
+      nsRefPtr<gfxContext> ctx = new gfxContext(imgSurface);
+      ctx->SetSource(aSurface);
+      ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+      ctx->Paint();
+    }
+
+    srcBuffer = aTarget->CreateSourceSurfaceFromData(imgSurface->Data(),
+                                                     IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height),
+                                                     imgSurface->Stride(),
+                                                     format);
+  }
+
+  srcBuffer->AddRef();
+  aSurface->SetData(&kSourceSurface, srcBuffer, SourceBufferDestroy);
+
+  return srcBuffer;
+}
+
+RefPtr<ScaledFont>
+gfxPlatform::GetScaledFontForFont(gfxFont *aFont)
+{
+  return NULL;
+}
+
+already_AddRefed<gfxASurface>
+gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
+{
+  // Don't know how to do this outside of Windows with D2D yet.
+  return NULL;
+}
+
 nsresult
 gfxPlatform::GetFontList(nsIAtom *aLangGroup,
                          const nsACString& aGenericFamily,
                          nsTArray<nsString>& aListOfFonts)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -61,16 +61,21 @@ struct gfxFontStyle;
 class gfxUserFontSet;
 class gfxFontEntry;
 class gfxProxyFontEntry;
 class gfxPlatformFontList;
 class gfxTextRun;
 class nsIURI;
 class nsIAtom;
 
+#include "gfx2DGlue.h"
+#include "mozilla/RefPtr.h"
+
+extern cairo_user_data_key_t kDrawTarget;
+
 // pref lang id's for font prefs
 // !!! needs to match the list of pref font.default.xx entries listed in all.js !!!
 // !!! don't use as bit mask, this may grow larger !!!
 
 enum eFontPrefLang {
     eFontPrefLang_Western     =  0,
     eFontPrefLang_CentEuro    =  1,
     eFontPrefLang_Japanese    =  2,
@@ -162,16 +167,28 @@ public:
      */
     virtual already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                                  gfxASurface::gfxContentType contentType) = 0;
 
 
     virtual already_AddRefed<gfxASurface> OptimizeImage(gfxImageSurface *aSurface,
                                                         gfxASurface::gfxImageFormat format);
 
+    virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
+      CreateDrawTargetForSurface(gfxASurface *aSurface);
+
+    virtual mozilla::RefPtr<mozilla::gfx::SourceSurface>
+      GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);
+
+    virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
+      GetScaledFontForFont(gfxFont *aFont);
+
+    virtual already_AddRefed<gfxASurface>
+      GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
+
     /*
      * Font bits
      */
 
     virtual void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
 
     /**
      * Fill aListOfFonts with the results of querying the list of font names
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -68,21 +68,25 @@
 #include "gfxDWriteCommon.h"
 #include <dwrite.h>
 #endif
 
 #include "gfxUserFontSet.h"
 
 #include <string>
 
+using namespace mozilla::gfx;
+
 #ifdef CAIRO_HAS_D2D_SURFACE
 #include "gfxD2DSurface.h"
 
 #include <d3d10_1.h>
 
+#include "mozilla/gfx/2D.h"
+
 #include "nsIMemoryReporter.h"
 #include "nsMemory.h"
 #endif
 
 using namespace mozilla;
 
 #ifdef CAIRO_HAS_D2D_SURFACE
 class D2DCacheReporter :
@@ -397,18 +401,20 @@ gfxWindowsPlatform::VerifyD2DDevice(PRBo
             mD2DDevice = cairo_d2d_create_device_from_d3d10device(device);
         }
     }
 
     if (!mD2DDevice && aAttemptForce) {
         mD2DDevice = cairo_d2d_create_device();
     }
 
-    if (mD2DDevice)
+    if (mD2DDevice) {
         reporter.SetSuccessful();
+        mozilla::gfx::Factory::SetDirect3D10Device(cairo_d2d_device_get_device(mD2DDevice));
+    }
 #endif
 }
 
 // bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd
 // crashers so blacklist them altogether
 
 #ifdef CAIRO_HAS_DWRITE_FONT
 #define WINDOWS7_RTM_BUILD 7600
@@ -478,16 +484,58 @@ gfxWindowsPlatform::CreateOffscreenSurfa
     if (surf == nsnull)
         surf = new gfxImageSurface(size, gfxASurface::FormatFromContent(contentType));
 
     NS_IF_ADDREF(surf);
 
     return surf;
 }
 
+RefPtr<ScaledFont>
+gfxWindowsPlatform::GetScaledFontForFont(gfxFont *aFont)
+{
+  if(mUseDirectWrite) {
+    gfxDWriteFont *font = static_cast<gfxDWriteFont*>(aFont);
+
+    NativeFont nativeFont;
+    nativeFont.mType = NATIVE_FONT_DWRITE_FONT_FACE;
+    nativeFont.mFont = font->GetFontFace();
+    RefPtr<ScaledFont> scaledFont =
+      mozilla::gfx::Factory::CreateScaledFontForNativeFont(nativeFont, font->GetAdjustedSize());
+
+    return scaledFont;
+  }
+}
+
+already_AddRefed<gfxASurface>
+gfxWindowsPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
+{
+#ifdef XP_WIN
+  if (aTarget->GetType() == BACKEND_DIRECT2D) {
+    RefPtr<ID3D10Texture2D> texture =
+      static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
+
+    if (!texture) {
+      return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
+    }
+
+    aTarget->Flush();
+
+    nsRefPtr<gfxASurface> surf =
+      new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
+
+    surf->SetData(&kDrawTarget, aTarget, NULL);
+
+    return surf.forget();
+  }
+#endif
+
+  return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
+}
+
 nsresult
 gfxWindowsPlatform::GetFontList(nsIAtom *aLangGroup,
                                 const nsACString& aGenericFamily,
                                 nsTArray<nsString>& aListOfFonts)
 {
     gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts);
 
     return NS_OK;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -122,16 +122,20 @@ public:
     static gfxWindowsPlatform *GetPlatform() {
         return (gfxWindowsPlatform*) gfxPlatform::GetPlatform();
     }
 
     virtual gfxPlatformFontList* CreatePlatformFontList();
 
     already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                          gfxASurface::gfxContentType contentType);
+    virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
+      GetScaledFontForFont(gfxFont *aFont);
+    virtual already_AddRefed<gfxASurface>
+      GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
 
     enum RenderMode {
         /* Use GDI and windows surfaces */
         RENDER_GDI = 0,
 
         /* Use 32bpp image surfaces and call StretchDIBits */
         RENDER_IMAGE_STRETCH32,