diff -r 000000000000 -r 6474c204b198 gfx/thebes/gfxPlatform.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/thebes/gfxPlatform.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,688 @@ +/* -*- 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/. */ + +#ifndef GFX_PLATFORM_H +#define GFX_PLATFORM_H + +#include "prlog.h" +#include "nsTArray.h" +#include "nsString.h" +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" + +#include "gfxTypes.h" +#include "nsRect.h" + +#include "qcms.h" + +#include "mozilla/RefPtr.h" +#include "GfxInfoCollector.h" + +#include "mozilla/layers/CompositorTypes.h" + +class gfxASurface; +class gfxImageSurface; +class gfxFont; +class gfxFontGroup; +struct gfxFontStyle; +class gfxUserFontSet; +class gfxFontEntry; +class gfxProxyFontEntry; +class gfxPlatformFontList; +class gfxTextRun; +class nsIURI; +class nsIAtom; +class nsIObserver; +struct gfxRGBA; + +namespace mozilla { +namespace gl { +class GLContext; +class SkiaGLGlue; +} +namespace gfx { +class DrawTarget; +class SourceSurface; +class DataSourceSurface; +class ScaledFont; +class DrawEventRecorder; + +inline uint32_t +BackendTypeBit(BackendType b) +{ + return 1 << uint8_t(b); +} +} +} + +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, + eFontPrefLang_ChineseTW = 3, + eFontPrefLang_ChineseCN = 4, + eFontPrefLang_ChineseHK = 5, + eFontPrefLang_Korean = 6, + eFontPrefLang_Cyrillic = 7, + eFontPrefLang_Baltic = 8, + eFontPrefLang_Greek = 9, + eFontPrefLang_Turkish = 10, + eFontPrefLang_Thai = 11, + eFontPrefLang_Hebrew = 12, + eFontPrefLang_Arabic = 13, + eFontPrefLang_Devanagari = 14, + eFontPrefLang_Tamil = 15, + eFontPrefLang_Armenian = 16, + eFontPrefLang_Bengali = 17, + eFontPrefLang_Canadian = 18, + eFontPrefLang_Ethiopic = 19, + eFontPrefLang_Georgian = 20, + eFontPrefLang_Gujarati = 21, + eFontPrefLang_Gurmukhi = 22, + eFontPrefLang_Khmer = 23, + eFontPrefLang_Malayalam = 24, + eFontPrefLang_Oriya = 25, + eFontPrefLang_Telugu = 26, + eFontPrefLang_Kannada = 27, + eFontPrefLang_Sinhala = 28, + eFontPrefLang_Tibetan = 29, + + eFontPrefLang_Others = 30, // x-unicode + + eFontPrefLang_CJKSet = 31 // special code for CJK set +}; + +enum eCMSMode { + eCMSMode_Off = 0, // No color management + eCMSMode_All = 1, // Color manage everything + eCMSMode_TaggedOnly = 2, // Color manage tagged Images Only + eCMSMode_AllCount = 3 +}; + +enum eGfxLog { + // all font enumerations, localized names, fullname/psnames, cmap loads + eGfxLog_fontlist = 0, + // timing info on font initialization + eGfxLog_fontinit = 1, + // dump text runs, font matching, system fallback for content + eGfxLog_textrun = 2, + // dump text runs, font matching, system fallback for chrome + eGfxLog_textrunui = 3, + // dump cmap coverage data as they are loaded + eGfxLog_cmapdata = 4, + // text perf data + eGfxLog_textperf = 5 +}; + +// when searching through pref langs, max number of pref langs +const uint32_t kMaxLenPrefLangList = 32; + +#define UNINITIALIZED_VALUE (-1) + +inline const char* +GetBackendName(mozilla::gfx::BackendType aBackend) +{ + switch (aBackend) { + case mozilla::gfx::BackendType::DIRECT2D: + return "direct2d"; + case mozilla::gfx::BackendType::COREGRAPHICS_ACCELERATED: + return "quartz accelerated"; + case mozilla::gfx::BackendType::COREGRAPHICS: + return "quartz"; + case mozilla::gfx::BackendType::CAIRO: + return "cairo"; + case mozilla::gfx::BackendType::SKIA: + return "skia"; + case mozilla::gfx::BackendType::RECORDING: + return "recording"; + case mozilla::gfx::BackendType::DIRECT2D1_1: + return "direct2d 1.1"; + case mozilla::gfx::BackendType::NONE: + return "none"; + } + MOZ_CRASH("Incomplete switch"); +} + +class gfxPlatform { +public: + typedef mozilla::gfx::IntSize IntSize; + + /** + * 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(); + + + /** + * Shut down Thebes. + * Init() arranges for this to be called at an appropriate time. + */ + static void Shutdown(); + + /** + * Create an offscreen surface of the given dimensions + * and image format. + */ + virtual already_AddRefed + CreateOffscreenSurface(const IntSize& size, + gfxContentType contentType) = 0; + + /** + * Create an offscreen surface of the given dimensions and image format which + * can be converted to a gfxImageSurface without copying. If we can provide + * a platform-hosted surface, then we will return that instead of an actual + * gfxImageSurface. + * Sub-classes should override this method if CreateOffscreenSurface returns a + * surface which implements GetAsImageSurface + */ + virtual already_AddRefed + CreateOffscreenImageSurface(const gfxIntSize& aSize, + gfxContentType aContentType); + + virtual already_AddRefed OptimizeImage(gfxImageSurface *aSurface, + gfxImageFormat format); + + /** + * Beware that these methods may return DrawTargets which are not fully supported + * on the current platform and might fail silently in subtle ways. This is a massive + * potential footgun. You should only use these methods for canvas drawing really. + * Use extreme caution if you use them for content where you are not 100% sure we + * support the DrawTarget we get back. + * See SupportsAzureContentForDrawTarget. + */ + virtual mozilla::RefPtr + CreateDrawTargetForSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize); + + virtual mozilla::RefPtr + CreateDrawTargetForUpdateSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize); + + /* + * Creates a SourceSurface for a gfxASurface. This function does no caching, + * so the caller should cache the gfxASurface if it will be used frequently. + * The returned surface keeps a reference to aTarget, so it is OK to keep the + * surface, even if aTarget changes. + * aTarget should not keep a reference to the returned surface because that + * will cause a cycle. + */ + virtual mozilla::RefPtr + GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface); + + static void ClearSourceSurfaceForSurface(gfxASurface *aSurface); + + static mozilla::RefPtr + GetWrappedDataSourceSurface(gfxASurface *aSurface); + + virtual mozilla::TemporaryRef + GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont); + + virtual already_AddRefed + GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget); + + mozilla::RefPtr + CreateOffscreenContentDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat); + + mozilla::RefPtr + CreateOffscreenCanvasDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat); + + virtual mozilla::RefPtr + CreateDrawTargetForData(unsigned char* aData, const mozilla::gfx::IntSize& aSize, + int32_t aStride, mozilla::gfx::SurfaceFormat aFormat); + + /** + * Returns true if we should use Azure to render content with aTarget. For + * example, it is possible that we are using Direct2D for rendering and thus + * using Azure. But we want to render to a CairoDrawTarget, in which case + * SupportsAzureContent will return true but SupportsAzureContentForDrawTarget + * will return false. + */ + bool SupportsAzureContentForDrawTarget(mozilla::gfx::DrawTarget* aTarget); + + bool SupportsAzureContentForType(mozilla::gfx::BackendType aType) { + return BackendTypeBit(aType) & mContentBackendBitmask; + } + + virtual bool UseAcceleratedSkiaCanvas(); + virtual void InitializeSkiaCacheLimits(); + + void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) { + aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend)); + aObj.DefineProperty("AzureSkiaAccelerated", UseAcceleratedSkiaCanvas()); + aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend)); + aObj.DefineProperty("AzureContentBackend", GetBackendName(mContentBackend)); + } + + mozilla::gfx::BackendType GetContentBackend() { + return mContentBackend; + } + + mozilla::gfx::BackendType GetPreferredCanvasBackend() { + return mPreferredCanvasBackend; + } + + /* + * Font bits + */ + + virtual void SetupClusterBoundaries(gfxTextRun *aTextRun, const char16_t *aString); + + /** + * Fill aListOfFonts with the results of querying the list of font names + * that correspond to the given language group or generic font family + * (or both, or neither). + */ + virtual nsresult GetFontList(nsIAtom *aLangGroup, + const nsACString& aGenericFamily, + nsTArray& aListOfFonts); + + /** + * Rebuilds the any cached system font lists + */ + virtual nsresult UpdateFontList(); + + /** + * Create the platform font-list object (gfxPlatformFontList concrete subclass). + * This function is responsible to create the appropriate subclass of + * gfxPlatformFontList *and* to call its InitFontList() method. + */ + virtual gfxPlatformFontList *CreatePlatformFontList() { + NS_NOTREACHED("oops, this platform doesn't have a gfxPlatformFontList implementation"); + return nullptr; + } + + /** + * Font name resolver, this returns actual font name(s) by the callback + * function. If the font doesn't exist, the callback function is not called. + * If the callback function returns false, the aAborted value is set to + * true, otherwise, false. + */ + typedef bool (*FontResolverCallback) (const nsAString& aName, + void *aClosure); + virtual nsresult ResolveFontName(const nsAString& aFontName, + FontResolverCallback aCallback, + void *aClosure, + bool& aAborted) = 0; + + /** + * Resolving a font name to family name. The result MUST be in the result of GetFontList(). + * If the name doesn't in the system, aFamilyName will be empty string, but not failed. + */ + virtual nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) = 0; + + /** + * Create the appropriate platform font group + */ + virtual gfxFontGroup *CreateFontGroup(const nsAString& aFamilies, + const gfxFontStyle *aStyle, + gfxUserFontSet *aUserFontSet) = 0; + + + /** + * Look up a local platform font using the full font face name. + * (Needed to support @font-face src local().) + * Ownership of the returned gfxFontEntry is passed to the caller, + * who must either AddRef() or delete. + */ + virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, + const nsAString& aFontName) + { return nullptr; } + + /** + * Activate a platform font. (Needed to support @font-face src url().) + * aFontData is a NS_Malloc'ed block that must be freed by this function + * (or responsibility passed on) when it is no longer needed; the caller + * will NOT free it. + * Ownership of the returned gfxFontEntry is passed to the caller, + * who must either AddRef() or delete. + */ + virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, + const uint8_t *aFontData, + uint32_t aLength); + + /** + * Whether to allow downloadable fonts via @font-face rules + */ + bool DownloadableFontsEnabled(); + + /** + * True when hinting should be enabled. This setting shouldn't + * change per gecko process, while the process is live. If so the + * results are not defined. + * + * NB: this bit is only honored by the FT2 backend, currently. + */ + virtual bool FontHintingEnabled() { return true; } + + /** + * True when zooming should not require reflow, so glyph metrics and + * positioning should not be adjusted for device pixels. + * If this is TRUE, then FontHintingEnabled() should be FALSE, + * but the converse is not necessarily required; in particular, + * B2G always has FontHintingEnabled FALSE, but RequiresLinearZoom + * is only true for the browser process, not Gaia or other apps. + * + * Like FontHintingEnabled (above), this setting shouldn't + * change per gecko process, while the process is live. If so the + * results are not defined. + * + * NB: this bit is only honored by the FT2 backend, currently. + */ + virtual bool RequiresLinearZoom() { return false; } + + /** + * Whether to check all font cmaps during system font fallback + */ + bool UseCmapsDuringSystemFallback(); + + /** + * Whether to render SVG glyphs within an OpenType font wrapper + */ + bool OpenTypeSVGEnabled(); + + /** + * Max character length of words in the word cache + */ + uint32_t WordCacheCharLimit(); + + /** + * Max number of entries in word cache + */ + uint32_t WordCacheMaxEntries(); + + /** + * Whether to use the SIL Graphite rendering engine + * (for fonts that include Graphite tables) + */ + bool UseGraphiteShaping(); + + /** + * Whether to use the harfbuzz shaper (depending on script complexity). + * + * This allows harfbuzz to be enabled selectively via the preferences. + */ + bool UseHarfBuzzForScript(int32_t aScriptCode); + + // check whether format is supported on a platform or not (if unclear, returns true) + virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) { return false; } + + void GetPrefFonts(nsIAtom *aLanguage, nsString& array, bool aAppendUnicode = true); + + // in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs + void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang); + + /** + * Iterate over pref fonts given a list of lang groups. For a single lang + * group, multiple pref fonts are possible. If error occurs, returns false, + * true otherwise. Callback returns false to abort process. + */ + typedef bool (*PrefFontCallback) (eFontPrefLang aLang, const nsAString& aName, + void *aClosure); + static bool ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArrayLen, + PrefFontCallback aCallback, + void *aClosure); + + // convert a lang group to enum constant (i.e. "zh-TW" ==> eFontPrefLang_ChineseTW) + static eFontPrefLang GetFontPrefLangFor(const char* aLang); + + // convert a lang group atom to enum constant + static eFontPrefLang GetFontPrefLangFor(nsIAtom *aLang); + + // convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW ==> "zh-TW") + static const char* GetPrefLangName(eFontPrefLang aLang); + + // map a Unicode range (based on char code) to a font language for Preferences + static eFontPrefLang GetFontPrefLangFor(uint8_t aUnicodeRange); + + // returns true if a pref lang is CJK + static bool IsLangCJK(eFontPrefLang aLang); + + // helper method to add a pref lang to an array, if not already in array + static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang); + + // returns a list of commonly used fonts for a given character + // these are *possible* matches, no cmap-checking is done at this level + virtual void GetCommonFallbackFonts(const uint32_t /*aCh*/, + int32_t /*aRunScript*/, + nsTArray& /*aFontList*/) + { + // platform-specific override, by default do nothing + } + + static bool OffMainThreadCompositingEnabled(); + + /** Use gfxPlatform::GetPref* methods instead of direct calls to Preferences + * to get the values for layers preferences. These will only be evaluated + * only once, and remain the same until restart. + */ + static bool GetPrefLayersOffMainThreadCompositionEnabled(); + static bool CanUseDirect3D9(); + + static bool OffMainThreadCompositionRequired(); + + /** + * Is it possible to use buffer rotation. Note that these + * check the preference, but also allow for the override to + * disable it using DisableBufferRotation. + */ + static bool BufferRotationEnabled(); + static void DisableBufferRotation(); + + /** + * Are we going to try color management? + */ + static eCMSMode GetCMSMode(); + + /** + * Determines the rendering intent for color management. + * + * If the value in the pref gfx.color_management.rendering_intent is a + * valid rendering intent as defined in gfx/qcms/qcms.h, that + * value is returned. Otherwise, -1 is returned and the embedded intent + * should be used. + * + * See bug 444014 for details. + */ + static int GetRenderingIntent(); + + /** + * Convert a pixel using a cms transform in an endian-aware manner. + * + * Sets 'out' to 'in' if transform is nullptr. + */ + static void TransformPixel(const gfxRGBA& in, gfxRGBA& out, qcms_transform *transform); + + /** + * Return the output device ICC profile. + */ + static qcms_profile* GetCMSOutputProfile(); + + /** + * Return the sRGB ICC profile. + */ + static qcms_profile* GetCMSsRGBProfile(); + + /** + * Return sRGB -> output device transform. + */ + static qcms_transform* GetCMSRGBTransform(); + + /** + * Return output -> sRGB device transform. + */ + static qcms_transform* GetCMSInverseRGBTransform(); + + /** + * Return sRGBA -> output device transform. + */ + static qcms_transform* GetCMSRGBATransform(); + + virtual void FontsPrefsChanged(const char *aPref); + + int32_t GetBidiNumeralOption(); + + /** + * Returns a 1x1 surface that can be used to create graphics contexts + * for measuring text etc as if they will be rendered to the screen + */ + gfxASurface* ScreenReferenceSurface() { return mScreenReferenceSurface; } + mozilla::gfx::DrawTarget* ScreenReferenceDrawTarget() { return mScreenReferenceDrawTarget; } + + virtual mozilla::gfx::SurfaceFormat Optimal2DFormatForContent(gfxContentType aContent); + + virtual gfxImageFormat OptimalFormatForContent(gfxContentType aContent); + + virtual gfxImageFormat GetOffscreenFormat() + { return gfxImageFormat::RGB24; } + + /** + * Returns a logger if one is available and logging is enabled + */ + static PRLogModuleInfo* GetLog(eGfxLog aWhichLog); + + virtual int GetScreenDepth() const; + + /** + * Return the layer debugging options to use browser-wide. + */ + mozilla::layers::DiagnosticTypes GetLayerDiagnosticTypes(); + + static nsIntRect FrameCounterBounds() { + int bits = 16; + int sizeOfBit = 3; + return nsIntRect(0, 0, bits * sizeOfBit, sizeOfBit); + } + + /** + * Returns true if we should use raw memory to send data to the compositor + * rather than using shmems. + * + * This method should not be called from the compositor thread. + */ + bool PreferMemoryOverShmem() const; + + mozilla::gl::SkiaGLGlue* GetSkiaGLGlue(); + void PurgeSkiaCache(); + + virtual bool IsInGonkEmulator() const { return false; } + +protected: + gfxPlatform(); + virtual ~gfxPlatform(); + + void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, + eFontPrefLang aCharLang, eFontPrefLang aPageLang); + + /** + * Helper method, creates a draw target for a specific Azure backend. + * Used by CreateOffscreenDrawTarget. + */ + mozilla::RefPtr + CreateDrawTargetForBackend(mozilla::gfx::BackendType aBackend, + const mozilla::gfx::IntSize& aSize, + mozilla::gfx::SurfaceFormat aFormat); + + /** + * Initialise the preferred and fallback canvas backends + * aBackendBitmask specifies the backends which are acceptable to the caller. + * The backend used is determined by aBackendBitmask and the order specified + * by the gfx.canvas.azure.backends pref. + */ + void InitBackendPrefs(uint32_t aCanvasBitmask, mozilla::gfx::BackendType aCanvasDefault, + uint32_t aContentBitmask, mozilla::gfx::BackendType aContentDefault); + + /** + * returns the first backend named in the pref gfx.canvas.azure.backends + * which is a component of aBackendBitmask, a bitmask of backend types + */ + static mozilla::gfx::BackendType GetCanvasBackendPref(uint32_t aBackendBitmask); + + /** + * returns the first backend named in the pref gfx.content.azure.backend + * which is a component of aBackendBitmask, a bitmask of backend types + */ + static mozilla::gfx::BackendType GetContentBackendPref(uint32_t &aBackendBitmask); + + /** + * Will return the first backend named in aBackendPrefName + * allowed by aBackendBitmask, a bitmask of backend types. + * It also modifies aBackendBitmask to only include backends that are + * allowed given the prefs. + */ + static mozilla::gfx::BackendType GetBackendPref(const char* aBackendPrefName, + uint32_t &aBackendBitmask); + /** + * Decode the backend enumberation from a string. + */ + static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName); + + static mozilla::TemporaryRef + GetScaledFontForFontWithCairoSkia(mozilla::gfx::DrawTarget* aTarget, gfxFont* aFont); + + int8_t mAllowDownloadableFonts; + int8_t mGraphiteShapingEnabled; + int8_t mOpenTypeSVGEnabled; + + int8_t mBidiNumeralOption; + + // whether to always search font cmaps globally + // when doing system font fallback + int8_t mFallbackUsesCmaps; + + // which scripts should be shaped with harfbuzz + int32_t mUseHarfBuzzScripts; + + // max character limit for words in word cache + int32_t mWordCacheCharLimit; + + // max number of entries in word cache + int32_t mWordCacheMaxEntries; + +private: + /** + * Start up Thebes. + */ + static void Init(); + + static void CreateCMSOutputProfile(); + + static void GetCMSOutputProfileData(void *&mem, size_t &size); + + friend void RecordingPrefChanged(const char *aPrefName, void *aClosure); + + virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size); + + virtual bool SupportsOffMainThreadCompositing() { return true; } + + nsRefPtr mScreenReferenceSurface; + mozilla::RefPtr mScreenReferenceDrawTarget; + nsTArray mCJKPrefLangs; + nsCOMPtr mSRGBOverrideObserver; + nsCOMPtr mFontPrefsObserver; + nsCOMPtr mMemoryPressureObserver; + + // The preferred draw target backend to use for canvas + mozilla::gfx::BackendType mPreferredCanvasBackend; + // The fallback draw target backend to use for canvas, if the preferred backend fails + mozilla::gfx::BackendType mFallbackCanvasBackend; + // The backend to use for content + mozilla::gfx::BackendType mContentBackend; + // Bitmask of backend types we can use to render content + uint32_t mContentBackendBitmask; + + mozilla::widget::GfxInfoCollector mAzureCanvasBackendCollector; + + mozilla::RefPtr mRecorder; + bool mLayersPreferMemoryOverShmem; + mozilla::RefPtr mSkiaGlue; +}; + +#endif /* GFX_PLATFORM_H */