1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxCachedTempSurface.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,106 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; 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 +#include "gfxCachedTempSurface.h" 1.10 +#include "gfxContext.h" 1.11 +#include "mozilla/Attributes.h" 1.12 + 1.13 +class CachedSurfaceExpirationTracker MOZ_FINAL : 1.14 + public nsExpirationTracker<gfxCachedTempSurface,2> { 1.15 + 1.16 +public: 1.17 + // With K = 2, this means that surfaces will be released when they are not 1.18 + // used for 1-2 seconds. 1.19 + enum { TIMEOUT_MS = 1000 }; 1.20 + CachedSurfaceExpirationTracker() 1.21 + : nsExpirationTracker<gfxCachedTempSurface,2>(TIMEOUT_MS) {} 1.22 + 1.23 + ~CachedSurfaceExpirationTracker() { 1.24 + AgeAllGenerations(); 1.25 + } 1.26 + 1.27 + virtual void NotifyExpired(gfxCachedTempSurface* aSurface) { 1.28 + RemoveObject(aSurface); 1.29 + aSurface->Expire(); 1.30 + } 1.31 + 1.32 + static void MarkSurfaceUsed(gfxCachedTempSurface* aSurface) 1.33 + { 1.34 + if (aSurface->GetExpirationState()->IsTracked()) { 1.35 + sExpirationTracker->MarkUsed(aSurface); 1.36 + return; 1.37 + } 1.38 + 1.39 + if (!sExpirationTracker) { 1.40 + sExpirationTracker = new CachedSurfaceExpirationTracker(); 1.41 + } 1.42 + sExpirationTracker->AddObject(aSurface); 1.43 + } 1.44 + 1.45 + static void RemoveSurface(gfxCachedTempSurface* aSurface) 1.46 + { 1.47 + if (!sExpirationTracker) 1.48 + return; 1.49 + 1.50 + if (aSurface->GetExpirationState()->IsTracked()) { 1.51 + sExpirationTracker->RemoveObject(aSurface); 1.52 + } 1.53 + if (sExpirationTracker->IsEmpty()) { 1.54 + delete sExpirationTracker; 1.55 + sExpirationTracker = nullptr; 1.56 + } 1.57 + } 1.58 + 1.59 +private: 1.60 + static CachedSurfaceExpirationTracker* sExpirationTracker; 1.61 +}; 1.62 + 1.63 +CachedSurfaceExpirationTracker* 1.64 +CachedSurfaceExpirationTracker::sExpirationTracker = nullptr; 1.65 + 1.66 +gfxCachedTempSurface::~gfxCachedTempSurface() 1.67 +{ 1.68 + CachedSurfaceExpirationTracker::RemoveSurface(this); 1.69 +} 1.70 + 1.71 +already_AddRefed<gfxContext> 1.72 +gfxCachedTempSurface::Get(gfxContentType aContentType, 1.73 + const gfxRect& aRect, 1.74 + gfxASurface* aSimilarTo) 1.75 +{ 1.76 + if (mSurface) { 1.77 + /* Verify the current buffer is valid for this purpose */ 1.78 + if (mSize.width < aRect.width || mSize.height < aRect.height 1.79 + || mSurface->GetContentType() != aContentType 1.80 + || mType != aSimilarTo->GetType()) { 1.81 + mSurface = nullptr; 1.82 + } 1.83 + } 1.84 + 1.85 + bool cleared = false; 1.86 + if (!mSurface) { 1.87 + mSize = gfxIntSize(int32_t(ceil(aRect.width)), int32_t(ceil(aRect.height))); 1.88 + mSurface = aSimilarTo->CreateSimilarSurface(aContentType, mSize); 1.89 + if (!mSurface) 1.90 + return nullptr; 1.91 + 1.92 + cleared = true; 1.93 + mType = aSimilarTo->GetType(); 1.94 + } 1.95 + mSurface->SetDeviceOffset(-aRect.TopLeft()); 1.96 + 1.97 + nsRefPtr<gfxContext> ctx = new gfxContext(mSurface); 1.98 + ctx->Rectangle(aRect); 1.99 + ctx->Clip(); 1.100 + if (!cleared && aContentType != gfxContentType::COLOR) { 1.101 + ctx->SetOperator(gfxContext::OPERATOR_CLEAR); 1.102 + ctx->Paint(); 1.103 + ctx->SetOperator(gfxContext::OPERATOR_OVER); 1.104 + } 1.105 + 1.106 + CachedSurfaceExpirationTracker::MarkSurfaceUsed(this); 1.107 + 1.108 + return ctx.forget(); 1.109 +}