Bug 761397 - Part 1: Cache ID2D1Layers for D2D Azure backend. r=jrmuizel

This commit is contained in:
Bas Schouten 2012-06-20 23:41:16 +02:00
Родитель fecc69df4f
Коммит a76e2ac169
2 изменённых файлов: 54 добавлений и 9 удалений

Просмотреть файл

@ -152,7 +152,8 @@ private:
}; };
DrawTargetD2D::DrawTargetD2D() DrawTargetD2D::DrawTargetD2D()
: mClipsArePushed(false) : mCurrentCachedLayer(0)
, mClipsArePushed(false)
, mPrivateData(NULL) , mPrivateData(NULL)
{ {
} }
@ -183,6 +184,13 @@ DrawTargetD2D::~DrawTargetD2D()
// mSnapshot will be cleared now. // mSnapshot will be cleared now.
} }
for (int i = 0; i < kLayerCacheSize; i++) {
if (mCachedLayers[i]) {
mCachedLayers[i] = NULL;
mVRAMUsageDT -= GetByteSize();
}
}
// Targets depending on us can break that dependency, since we're obviously not going to // Targets depending on us can break that dependency, since we're obviously not going to
// be modified in the future. // be modified in the future.
for (TargetSet::iterator iter = mDependentTargets.begin(); for (TargetSet::iterator iter = mDependentTargets.begin();
@ -914,7 +922,9 @@ DrawTargetD2D::Mask(const Pattern &aSource,
RefPtr<ID2D1Brush> maskBrush = CreateBrushForPattern(aMask, 1.0f); RefPtr<ID2D1Brush> maskBrush = CreateBrushForPattern(aMask, 1.0f);
RefPtr<ID2D1Layer> layer; RefPtr<ID2D1Layer> layer;
rt->CreateLayer(byRef(layer));
layer = GetCachedLayer();
rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), NULL, rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), NULL,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::IdentityMatrix(), D2D1::IdentityMatrix(),
@ -926,7 +936,7 @@ DrawTargetD2D::Mask(const Pattern &aSource,
mat.Invert(); mat.Invert();
rt->FillRectangle(D2DRect(mat.TransformBounds(rect)), brush); rt->FillRectangle(D2DRect(mat.TransformBounds(rect)), brush);
rt->PopLayer(); PopCachedLayer(rt);
FinalizeRTForOperation(aOptions.mCompositionOp, aSource, Rect(0, 0, (Float)mSize.width, (Float)mSize.height)); FinalizeRTForOperation(aOptions.mCompositionOp, aSource, Rect(0, 0, (Float)mSize.width, (Float)mSize.height));
} }
@ -948,12 +958,10 @@ DrawTargetD2D::PushClip(const Path *aPath)
clip.mTransform = D2DMatrix(mTransform); clip.mTransform = D2DMatrix(mTransform);
clip.mPath = pathD2D; clip.mPath = pathD2D;
RefPtr<ID2D1Layer> layer;
pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds); pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds);
clip.mLayer = GetCachedLayer();
mRT->CreateLayer( byRef(layer));
clip.mLayer = layer;
mPushedClips.push_back(clip); mPushedClips.push_back(clip);
// The transform of clips is relative to the world matrix, since we use the total // The transform of clips is relative to the world matrix, since we use the total
@ -971,7 +979,7 @@ DrawTargetD2D::PushClip(const Path *aPath)
mRT->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), pathD2D->mGeometry, mRT->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), pathD2D->mGeometry,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
clip.mTransform, 1.0f, NULL, clip.mTransform, 1.0f, NULL,
options), layer); options), clip.mLayer);
} }
} }
@ -1015,7 +1023,7 @@ DrawTargetD2D::PopClip()
mCurrentClippedGeometry = NULL; mCurrentClippedGeometry = NULL;
if (mClipsArePushed) { if (mClipsArePushed) {
if (mPushedClips.back().mLayer) { if (mPushedClips.back().mLayer) {
mRT->PopLayer(); PopCachedLayer(mRT);
} else { } else {
mRT->PopAxisAlignedClip(); mRT->PopAxisAlignedClip();
} }
@ -1286,6 +1294,32 @@ DrawTargetD2D::GetByteSize() const
return mSize.width * mSize.height * BytesPerPixel(mFormat); return mSize.width * mSize.height * BytesPerPixel(mFormat);
} }
TemporaryRef<ID2D1Layer>
DrawTargetD2D::GetCachedLayer()
{
RefPtr<ID2D1Layer> layer;
if (mCurrentCachedLayer < 5) {
if (!mCachedLayers[mCurrentCachedLayer]) {
mRT->CreateLayer(byRef(mCachedLayers[mCurrentCachedLayer]));
mVRAMUsageDT += GetByteSize();
}
layer = mCachedLayers[mCurrentCachedLayer];
} else {
mRT->CreateLayer(byRef(layer));
}
mCurrentCachedLayer++;
return layer;
}
void
DrawTargetD2D::PopCachedLayer(ID2D1RenderTarget *aRT)
{
aRT->PopLayer();
mCurrentCachedLayer--;
}
bool bool
DrawTargetD2D::InitD2DRenderTarget() DrawTargetD2D::InitD2DRenderTarget()
{ {

Просмотреть файл

@ -30,6 +30,8 @@ class SourceSurfaceD2D;
class GradientStopsD2D; class GradientStopsD2D;
class ScaledFontDWrite; class ScaledFontDWrite;
const int32_t kLayerCacheSize = 5;
struct PrivateD3D10DataD2D struct PrivateD3D10DataD2D
{ {
RefPtr<ID3D10Effect> mEffect; RefPtr<ID3D10Effect> mEffect;
@ -122,6 +124,8 @@ public:
bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
bool InitD3D10Data(); bool InitD3D10Data();
uint32_t GetByteSize() const; uint32_t GetByteSize() const;
TemporaryRef<ID2D1Layer> GetCachedLayer();
void PopCachedLayer(ID2D1RenderTarget *aRT);
static ID2D1Factory *factory(); static ID2D1Factory *factory();
static TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions); static TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions);
@ -219,6 +223,13 @@ private:
RefPtr<PathD2D> mPath; RefPtr<PathD2D> mPath;
}; };
std::vector<PushedClip> mPushedClips; std::vector<PushedClip> mPushedClips;
// We cache ID2D1Layer objects as it causes D2D to keep around textures that
// serve as the temporary surfaces for these operations. As texture creation
// is quite expensive this considerably improved performance.
// Careful here, RAII will not ensure destruction of the RefPtrs.
RefPtr<ID2D1Layer> mCachedLayers[kLayerCacheSize];
uint32_t mCurrentCachedLayer;
// The latest snapshot of this surface. This needs to be told when this // The latest snapshot of this surface. This needs to be told when this
// target is modified. We keep it alive as a cache. // target is modified. We keep it alive as a cache.