1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/src/SurfaceCache.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,180 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/** 1.10 + * SurfaceCache is a service for caching temporary surfaces in imagelib. 1.11 + */ 1.12 + 1.13 +#ifndef MOZILLA_IMAGELIB_SURFACECACHE_H_ 1.14 +#define MOZILLA_IMAGELIB_SURFACECACHE_H_ 1.15 + 1.16 +#include "mozilla/HashFunctions.h" // for HashGeneric and AddToHash 1.17 +#include "gfxPoint.h" // for gfxSize 1.18 +#include "nsCOMPtr.h" // for already_AddRefed 1.19 +#include "mozilla/gfx/Point.h" // for mozilla::gfx::IntSize 1.20 +#include "SVGImageContext.h" // for SVGImageContext 1.21 + 1.22 +class gfxDrawable; 1.23 + 1.24 +namespace mozilla { 1.25 + 1.26 +namespace gfx { 1.27 +class DrawTarget; 1.28 +} // namespace gfx 1.29 + 1.30 +namespace image { 1.31 + 1.32 +class Image; 1.33 + 1.34 +/* 1.35 + * ImageKey contains the information we need to look up all cached surfaces for 1.36 + * a particular image. 1.37 + */ 1.38 +typedef Image* ImageKey; 1.39 + 1.40 +/* 1.41 + * SurfaceKey contains the information we need to look up a specific cached 1.42 + * surface. Together with an ImageKey, this uniquely identifies the surface. 1.43 + * 1.44 + * XXX(seth): Right now this is specialized to the needs of VectorImage. We'll 1.45 + * generalize it in bug 919071. 1.46 + */ 1.47 +class SurfaceKey 1.48 +{ 1.49 + typedef gfx::IntSize IntSize; 1.50 +public: 1.51 + SurfaceKey(const IntSize& aSize, 1.52 + const gfxSize aScale, 1.53 + const SVGImageContext* aSVGContext, 1.54 + const float aAnimationTime, 1.55 + const uint32_t aFlags) 1.56 + : mSize(aSize) 1.57 + , mScale(aScale) 1.58 + , mSVGContextIsValid(aSVGContext != nullptr) 1.59 + , mAnimationTime(aAnimationTime) 1.60 + , mFlags(aFlags) 1.61 + { 1.62 + // XXX(seth): Would love to use Maybe<T> here, but see bug 913586. 1.63 + if (mSVGContextIsValid) 1.64 + mSVGContext = *aSVGContext; 1.65 + } 1.66 + 1.67 + bool operator==(const SurfaceKey& aOther) const 1.68 + { 1.69 + bool matchesSVGContext = aOther.mSVGContextIsValid == mSVGContextIsValid && 1.70 + (!mSVGContextIsValid || aOther.mSVGContext == mSVGContext); 1.71 + return aOther.mSize == mSize && 1.72 + aOther.mScale == mScale && 1.73 + matchesSVGContext && 1.74 + aOther.mAnimationTime == mAnimationTime && 1.75 + aOther.mFlags == mFlags; 1.76 + } 1.77 + 1.78 + uint32_t Hash() const 1.79 + { 1.80 + uint32_t hash = HashGeneric(mSize.width, mSize.height); 1.81 + hash = AddToHash(hash, mScale.width, mScale.height); 1.82 + hash = AddToHash(hash, mSVGContextIsValid, mSVGContext.Hash()); 1.83 + hash = AddToHash(hash, mAnimationTime, mFlags); 1.84 + return hash; 1.85 + } 1.86 + 1.87 + IntSize Size() const { return mSize; } 1.88 + 1.89 +private: 1.90 + IntSize mSize; 1.91 + gfxSize mScale; 1.92 + SVGImageContext mSVGContext; 1.93 + bool mSVGContextIsValid; 1.94 + float mAnimationTime; 1.95 + uint32_t mFlags; 1.96 +}; 1.97 + 1.98 +/** 1.99 + * SurfaceCache is an imagelib-global service that allows caching of temporary 1.100 + * surfaces. Surfaces expire from the cache automatically if they go too long 1.101 + * without being accessed. 1.102 + * 1.103 + * SurfaceCache is not thread-safe; it should only be accessed from the main 1.104 + * thread. 1.105 + */ 1.106 +struct SurfaceCache 1.107 +{ 1.108 + typedef gfx::IntSize IntSize; 1.109 + 1.110 + /* 1.111 + * Initialize static data. Called during imagelib module initialization. 1.112 + */ 1.113 + static void Initialize(); 1.114 + 1.115 + /* 1.116 + * Release static data. Called during imagelib module shutdown. 1.117 + */ 1.118 + static void Shutdown(); 1.119 + 1.120 + /* 1.121 + * Look up a surface in the cache. 1.122 + * 1.123 + * @param aImageKey Key data identifying which image the surface belongs to. 1.124 + * @param aSurfaceKey Key data which uniquely identifies the requested surface. 1.125 + * 1.126 + * @return the requested surface, or nullptr if not found. 1.127 + */ 1.128 + static already_AddRefed<gfxDrawable> Lookup(const ImageKey aImageKey, 1.129 + const SurfaceKey& aSurfaceKey); 1.130 + 1.131 + /* 1.132 + * Insert a surface into the cache. It is an error to call this function 1.133 + * without first calling Lookup to verify that the surface is not already in 1.134 + * the cache. 1.135 + * 1.136 + * @param aTarget The new surface (in the form of a DrawTarget) to insert 1.137 + * into the cache. 1.138 + * @param aImageKey Key data identifying which image the surface belongs to. 1.139 + * @param aSurfaceKey Key data which uniquely identifies the requested surface. 1.140 + */ 1.141 + static void Insert(mozilla::gfx::DrawTarget* aTarget, 1.142 + const ImageKey aImageKey, 1.143 + const SurfaceKey& aSurfaceKey); 1.144 + 1.145 + /* 1.146 + * Checks if a surface of a given size could possibly be stored in the cache. 1.147 + * If CanHold() returns false, Insert() will always fail to insert the 1.148 + * surface, but the inverse is not true: Insert() may take more information 1.149 + * into account than just image size when deciding whether to cache the 1.150 + * surface, so Insert() may still fail even if CanHold() returns true. 1.151 + * 1.152 + * Use CanHold() to avoid the need to create a temporary surface when we know 1.153 + * for sure the cache can't hold it. 1.154 + * 1.155 + * @param aSize The dimensions of a surface in pixels. 1.156 + * 1.157 + * @return false if the surface cache can't hold a surface of that size. 1.158 + */ 1.159 + static bool CanHold(const IntSize& aSize); 1.160 + 1.161 + /* 1.162 + * Evicts any cached surfaces associated with the given image from the cache. 1.163 + * This MUST be called, at a minimum, when the image is destroyed. If 1.164 + * another image were allocated at the same address it could result in 1.165 + * subtle, difficult-to-reproduce bugs. 1.166 + * 1.167 + * @param aImageKey The image which should be removed from the cache. 1.168 + */ 1.169 + static void Discard(const ImageKey aImageKey); 1.170 + 1.171 + /* 1.172 + * Evicts all caches surfaces from ths cache. 1.173 + */ 1.174 + static void DiscardAll(); 1.175 + 1.176 +private: 1.177 + virtual ~SurfaceCache() = 0; // Forbid instantiation. 1.178 +}; 1.179 + 1.180 +} // namespace image 1.181 +} // namespace mozilla 1.182 + 1.183 +#endif // MOZILLA_IMAGELIB_SURFACECACHE_H_