Bug 375824. Centralize Thebes startup/shutdown sequence. r=vlad
authorroc+@cs.cmu.edu
Thu, 29 Mar 2007 14:48:46 -0700
changeset 218 3738e5f5ae6ba20e542593b46fab7023858c309a
parent 217 b565502573625b6b5b758d7bbe11965c9fac2595
child 219 002cfbb6738d51e879d4f1397a859afa7680e405
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs375824
milestone1.9a4pre
Bug 375824. Centralize Thebes startup/shutdown sequence. r=vlad
gfx/src/thebes/nsThebesGfxFactory.cpp
gfx/thebes/public/gfxPlatform.h
gfx/thebes/public/gfxTextRunCache.h
gfx/thebes/src/gfxPlatform.cpp
gfx/thebes/src/gfxQuartzFontCache.h
gfx/thebes/src/gfxTextRunCache.cpp
gfx/thebes/test/gfxFontSelectionTest.cpp
gfx/thebes/test/gfxTextRunPerfTest.cpp
layout/build/nsLayoutStatics.cpp
--- a/gfx/src/thebes/nsThebesGfxFactory.cpp
+++ b/gfx/src/thebes/nsThebesGfxFactory.cpp
@@ -138,17 +138,23 @@ static const nsModuleComponentInfo compo
     "@mozilla.org/gfx/blender;1",
     nsThebesBlenderConstructor },
   { "image frame",
     GFX_IMAGEFRAME_CID,
     "@mozilla.org/gfx/image/frame;2",
     gfxImageFrameConstructor },
 };
 
+PR_STATIC_CALLBACK(nsresult)
+nsThebesGfxModuleCtor(nsIModule *self)
+{
+    return gfxPlatform::Init();
+}
+
 PR_STATIC_CALLBACK(void)
 nsThebesGfxModuleDtor(nsIModule *self)
 {
     nsThebesDeviceContext::Shutdown();
     gfxPlatform::Shutdown();
 }
 
-NS_IMPL_NSGETMODULE_WITH_DTOR(nsGfxModule, components, nsThebesGfxModuleDtor)
-
+NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(nsGfxModule, components,
+                                   nsThebesGfxModuleCtor, nsThebesGfxModuleDtor)
--- a/gfx/thebes/public/gfxPlatform.h
+++ b/gfx/thebes/public/gfxPlatform.h
@@ -52,16 +52,21 @@ public:
     /**
      * Return a pointer to the current active platform.
      * This is a singleton; it contains mostly convenience
      * functions to obtain platform-specific objects.
      */
     static gfxPlatform *GetPlatform();
 
     /**
+     * Start up Thebes. This can fail.
+     */
+    static nsresult Init();
+
+    /**
      * Clean up static objects to shut down thebes.
      */
     static void Shutdown();
 
     /**
      * Return PR_TRUE if we're to use Glitz for acceleration.
      */
     static PRBool UseGlitz();
--- a/gfx/thebes/public/gfxTextRunCache.h
+++ b/gfx/thebes/public/gfxTextRunCache.h
@@ -51,16 +51,18 @@ public:
      * Get the global gfxTextRunCache.  You must call Init() before
      * calling this method.
      */
     static gfxTextRunCache* GetCache() {
         return mGlobalCache;
     }
 
     static nsresult Init();
+    // It's OK to call Shutdown if we never actually started or we already
+    // shut down.
     static void Shutdown();
 
     /* Will return a pointer to a gfxTextRun, which may or may not be from
      * the cache. If aCallerOwns is set to true, the caller owns the textrun
      * and must delete it. Otherwise the returned textrun is only valid until
      * the next GetOrMakeTextRun call and the caller must not delete it.
      */
     gfxTextRun *GetOrMakeTextRun (gfxContext* aContext, gfxFontGroup *aFontGroup,
@@ -71,17 +73,16 @@ public:
                                   const PRUnichar *aString, PRUint32 aLength,
                                   PRUint32 aAppUnitsPerDevUnit, PRBool aIsRTL,
                                   PRBool aEnableSpacing, PRBool *aCallerOwns);
 
 protected:
     gfxTextRunCache();
 
     static gfxTextRunCache *mGlobalCache;
-    static PRInt32 mGlobalCacheRefCount;
 
     /* A small container class to hold a gfxFontGroup ref and a string.
      * This is used as the key for the cache hash table; to avoid
      * copying a whole pile of strings every time we do a hash lookup.
      * we only create our own copy of the string when Realize() is called.
      * gfxTextRunCache calls Realize whenever it puts a new entry into
      * the hashtable.
      */
--- a/gfx/thebes/src/gfxPlatform.cpp
+++ b/gfx/thebes/src/gfxPlatform.cpp
@@ -36,62 +36,95 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "gfxPlatform.h"
 
 #if defined(XP_WIN)
 #include "gfxWindowsPlatform.h"
 #elif defined(XP_MACOSX)
 #include "gfxPlatformMac.h"
+#include "gfxQuartzFontCache.h"
 #elif defined(MOZ_WIDGET_GTK2)
 #include "gfxPlatformGtk.h"
 #elif defined(XP_BEOS)
 #include "gfxBeOSPlatform.h"
 #elif defined(XP_OS2)
 #include "gfxOS2Platform.h"
 #endif
 
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
+#include "gfxTextRunCache.h"
 
 #include "nsIPref.h"
 #include "nsServiceManagerUtils.h"
 
 #ifdef MOZ_ENABLE_GLITZ
 #include <stdlib.h>
 #endif
 
 #include "cairo.h"
 
 gfxPlatform *gPlatform = nsnull;
 int gGlitzState = -1;
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
-    if (!gPlatform) {
+    return gPlatform;
+}
+
+nsresult
+gfxPlatform::Init()
+{
+    NS_ASSERTION(!gPlatform, "Already started???");
 #if defined(XP_WIN)
-        gPlatform = new gfxWindowsPlatform;
+    gPlatform = new gfxWindowsPlatform;
 #elif defined(XP_MACOSX)
-        gPlatform = new gfxPlatformMac;
+    gPlatform = new gfxPlatformMac;
 #elif defined(MOZ_WIDGET_GTK2)
-        gPlatform = new gfxPlatformGtk;
+    gPlatform = new gfxPlatformGtk;
 #elif defined(XP_BEOS)
-        gPlatform = new gfxBeOSPlatform;
+    gPlatform = new gfxBeOSPlatform;
 #elif defined(XP_OS2)
-        gPlatform = new gfxOS2Platform;
+    gPlatform = new gfxOS2Platform;
 #endif
+    if (!gPlatform)
+        return NS_ERROR_OUT_OF_MEMORY;
+
+    nsresult rv;
+
+#if defined(XP_MACOSX)
+    rv = gfxQuartzFontCache::Init();
+    if (NS_FAILED(rv)) {
+        NS_ERROR("Could not initialize gfxQuartzFontCache");
+        Shutdown();
+        return rv;
+    }
+#endif
+
+    rv = gfxTextRunCache::Init();
+    if (NS_FAILED(rv)) {
+        NS_ERROR("Could not initialize gfxTextRunCache");
+        Shutdown();
+        return rv;
     }
 
-    return gPlatform;
+    return NS_OK;
 }
 
 void
 gfxPlatform::Shutdown()
 {
+    // These may be called before the corresponding subsystems have actually
+    // started up. That's OK, they can handle it.
+    gfxTextRunCache::Shutdown();
+#if defined(XP_MACOSX)
+    gfxQuartzFontCache::Shutdown();
+#endif
     delete gPlatform;
     gPlatform = nsnull;
 }
 
 gfxPlatform::~gfxPlatform()
 {
 #if 0 // Comment this out for now, until we fix bug 374680.
 
--- a/gfx/thebes/src/gfxQuartzFontCache.h
+++ b/gfx/thebes/src/gfxQuartzFontCache.h
@@ -100,21 +100,31 @@ protected:
     nsString mName;
     PRInt32 mWeight;
     PRUint32 mTraits;
 };
 
 class gfxQuartzFontCache {
 public:
     static gfxQuartzFontCache* SharedFontCache() {
-        if (!sSharedFontCache)
-            sSharedFontCache = new gfxQuartzFontCache();
         return sSharedFontCache;
     }
 
+    static nsresult Init() {
+        NS_ASSERTION(!sSharedFontCache, "What's this doing here?");
+        sSharedFontCache = new gfxQuartzFontCache();
+        return sSharedFontCache ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+    }
+    // It's OK to call Shutdown if we never actually started or if 
+    // we already shut down.
+    static void Shutdown() {
+        delete sSharedFontCache;
+        sSharedFontCache = nsnull;
+    }
+
     ATSUFontID FindATSUFontIDForFamilyAndStyle (const nsAString& aFamily,
                                                 const gfxFontStyle* aStyle);
 
     ATSUFontID GetDefaultATSUFontID (const gfxFontStyle* aStyle);
 
     void GetFontList (const nsACString& aLangGroup,
                       const nsACString& aGenericFamily,
                       nsStringArray& aListOfFonts);
--- a/gfx/thebes/src/gfxTextRunCache.cpp
+++ b/gfx/thebes/src/gfxTextRunCache.cpp
@@ -69,17 +69,16 @@ Is8Bit(const PRUnichar *aString, PRUint3
         if (0x0100 <= *aString)
             return PR_FALSE;
         ++aString;
     }
     return PR_TRUE;
 }
 
 gfxTextRunCache* gfxTextRunCache::mGlobalCache = nsnull;
-PRInt32 gfxTextRunCache::mGlobalCacheRefCount = 0;
 
 static int gDisableCache = -1;
 
 gfxTextRunCache::gfxTextRunCache()
 {
     if (getenv("MOZ_GFX_NO_TEXT_CACHE"))
         gDisableCache = 1;
     else
@@ -90,40 +89,32 @@ gfxTextRunCache::gfxTextRunCache()
 
     mLastUTF16Eviction = mLastASCIIEviction = PR_Now();
 }
 
 // static
 nsresult
 gfxTextRunCache::Init()
 {
-    // We only live on the UI thread, right?  ;)
-    ++mGlobalCacheRefCount;
+    NS_ASSERTION(!mGlobalCache, "Why do we have an mGlobalCache?");
+    mGlobalCache = new gfxTextRunCache();
 
-    if (mGlobalCacheRefCount == 1) {
-        NS_ASSERTION(!mGlobalCache, "Why do we have an mGlobalCache?");
-        mGlobalCache = new gfxTextRunCache();
-
-        if (!mGlobalCache) {
-            return NS_ERROR_OUT_OF_MEMORY;
-        }
+    if (!mGlobalCache) {
+        return NS_ERROR_OUT_OF_MEMORY;
     }
 
     return NS_OK;
 }
 
 // static
 void
 gfxTextRunCache::Shutdown()
 {
-    --mGlobalCacheRefCount;
-    if (mGlobalCacheRefCount == 0) {
-        delete mGlobalCache;
-        mGlobalCache = nsnull;
-    }
+    delete mGlobalCache;
+    mGlobalCache = nsnull;
 }    
 
 static PRUint32
 ComputeFlags(PRBool aIsRTL, PRBool aEnableSpacing)
 {
     PRUint32 flags = gfxTextRunFactory::TEXT_HAS_SURROGATES;
     if (aIsRTL) {
         flags |= gfxTextRunFactory::TEXT_IS_RTL;
--- a/gfx/thebes/test/gfxFontSelectionTest.cpp
+++ b/gfx/thebes/test/gfxFontSelectionTest.cpp
@@ -288,17 +288,16 @@ PRBool
 RunTest (TestEntry *test, gfxContext *ctx) {
     nsRefPtr<gfxFontGroup> fontGroup;
 
 #if defined(XP_WIN)
     fontGroup = new gfxWindowsFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle);
 #elif defined(MOZ_ENABLE_PANGO)
     fontGroup = new gfxPangoFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle);
 #elif defined(XP_MACOSX)
-    CocoaPoolInit();
     fontGroup = new gfxAtsuiFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle);
 #else
     return PR_FALSE;
 #endif
 
     nsAutoPtr<gfxTextRun> textRun;
     gfxTextRunFactory::Parameters params = {
       ctx, nsnull, nsnull, nsnull, nsnull, 0, 60,
@@ -336,22 +335,29 @@ RunTest (TestEntry *test, gfxContext *ct
 int
 main (int argc, char **argv) {
     int passed = 0;
     int failed = 0;
 
 #ifdef MOZ_WIDGET_GTK2
     gtk_init(&argc, &argv); 
 #endif
+#ifdef XP_MACOSX
+    CocoaPoolInit();
+#endif
 
     // Initialize XPCOM
     nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
     if (NS_FAILED(rv))
         return -1;
 
+    rv = gfxPlatform::Init();
+    if (NS_FAILED(rv))
+        return -1;
+
     // let's get all the xpcom goop out of the system
     fflush (stderr);
     fflush (stdout);
 
     // don't need to query, we might need to set up some prefs later
     if (0) {
         nsresult rv;
 
--- a/gfx/thebes/test/gfxTextRunPerfTest.cpp
+++ b/gfx/thebes/test/gfxTextRunPerfTest.cpp
@@ -111,17 +111,17 @@ RunTest (TestEntry *test, gfxContext *ct
         fontGroup = new gfxAtsuiFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16);
 #endif
     }
 
     nsAutoPtr<gfxTextRun> textRun;
     PRUint32 i;
     PRBool isASCII = PR_TRUE;
     for (i = 0; test->mString[i]; ++i) {
-        if (test->mString[i] >= 0x80) {
+        if (test->mString[i] & 0x80) {
             isASCII = PR_FALSE;
         }
     }
     gfxTextRunFactory::Parameters params = {
       ctx, nsnull, nsnull, nsnull, nsnull, 0, 60, 0
     };
     PRUint32 length;
     if (isASCII) {
@@ -153,16 +153,20 @@ main (int argc, char **argv) {
     CocoaPoolInit();
 #endif
 
     // Initialize XPCOM
     nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
     if (NS_FAILED(rv))
         return -1; 
 
+    rv = gfxPlatform::Init();
+    if (NS_FAILED(rv))
+        return -1;
+
     // let's get all the xpcom goop out of the system
     fflush (stderr);
     fflush (stdout);
 
     nsRefPtr<gfxContext> context = MakeContext();
 
     // Start timing
     PRIntervalTime start = PR_IntervalNow();
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -93,32 +93,25 @@
 #ifdef MOZ_SVG
 PRBool NS_SVGEnabled();
 #endif
 
 #ifndef MOZ_NO_INSPECTOR_APIS
 #include "inDOMView.h"
 #endif
 
-#ifdef MOZ_CAIRO_GFX
-#include "gfxTextRunCache.h"
-#endif
-
 #ifndef MOZILLA_PLAINTEXT_EDITOR_ONLY
 #include "nsHTMLEditor.h"
 #include "nsTextServicesDocument.h"
 #endif
 
 #include "nsError.h"
 #include "nsTraceRefcnt.h"
 
 static nsrefcnt sLayoutStaticRefcnt;
-#ifdef MOZ_CAIRO_GFX
-static PRBool initedGfxTextRunCache;
-#endif
 
 nsresult
 nsLayoutStatics::Initialize()
 {
   NS_ASSERTION(sLayoutStaticRefcnt == 0,
                "nsLayoutStatics isn't zero!");
 
   sLayoutStaticRefcnt = 1;
@@ -210,25 +203,16 @@ nsLayoutStatics::Initialize()
   }
 
   rv = nsDOMStorageManager::Initialize();
   if (NS_FAILED(rv)) {
     NS_ERROR("Could not initialize nsDOMStorageManager");
     return rv;
   }
 
-#ifdef MOZ_CAIRO_GFX
-  rv = gfxTextRunCache::Init();
-  initedGfxTextRunCache = PR_TRUE;  
-  if (NS_FAILED(rv)) {
-    NS_ERROR("Could not initialize gfxTextRunCache");
-    return rv;
-  }
-#endif
-  
   return NS_OK;
 }
 
 void
 nsLayoutStatics::Shutdown()
 {
   nsDOMStorageManager::Shutdown();
   txMozillaXSLTProcessor::Shutdown();
@@ -288,22 +272,16 @@ nsLayoutStatics::Shutdown()
   nsTextControlFrame::ShutDown();
   nsXBLWindowKeyHandler::ShutDown();
   nsAutoCopyListener::Shutdown();
 
 #ifndef MOZILLA_PLAINTEXT_EDITOR_ONLY
   nsHTMLEditor::Shutdown();
   nsTextServicesDocument::Shutdown();
 #endif
-
-#ifdef MOZ_CAIRO_GFX
-  if (initedGfxTextRunCache) {
-    gfxTextRunCache::Shutdown();
-  }  
-#endif
 }
 
 void
 nsLayoutStatics::AddRef()
 {
   NS_ASSERTION(sLayoutStaticRefcnt,
                "nsLayoutStatics already dropped to zero!");