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()
: mClipsArePushed(false)
: mCurrentCachedLayer(0)
, mClipsArePushed(false)
, mPrivateData(NULL)
{
}
@ -183,6 +184,13 @@ DrawTargetD2D::~DrawTargetD2D()
// 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
// be modified in the future.
for (TargetSet::iterator iter = mDependentTargets.begin();
@ -914,7 +922,9 @@ DrawTargetD2D::Mask(const Pattern &aSource,
RefPtr<ID2D1Brush> maskBrush = CreateBrushForPattern(aMask, 1.0f);
RefPtr<ID2D1Layer> layer;
rt->CreateLayer(byRef(layer));
layer = GetCachedLayer();
rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), NULL,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::IdentityMatrix(),
@ -926,7 +936,7 @@ DrawTargetD2D::Mask(const Pattern &aSource,
mat.Invert();
rt->FillRectangle(D2DRect(mat.TransformBounds(rect)), brush);
rt->PopLayer();
PopCachedLayer(rt);
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.mPath = pathD2D;
RefPtr<ID2D1Layer> layer;
pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds);
clip.mLayer = GetCachedLayer();
mRT->CreateLayer( byRef(layer));
clip.mLayer = layer;
mPushedClips.push_back(clip);
// 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,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
clip.mTransform, 1.0f, NULL,
options), layer);
options), clip.mLayer);
}
}
@ -1015,7 +1023,7 @@ DrawTargetD2D::PopClip()
mCurrentClippedGeometry = NULL;
if (mClipsArePushed) {
if (mPushedClips.back().mLayer) {
mRT->PopLayer();
PopCachedLayer(mRT);
} else {
mRT->PopAxisAlignedClip();
}
@ -1286,6 +1294,32 @@ DrawTargetD2D::GetByteSize() const
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
DrawTargetD2D::InitD2DRenderTarget()
{

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

@ -30,6 +30,8 @@ class SourceSurfaceD2D;
class GradientStopsD2D;
class ScaledFontDWrite;
const int32_t kLayerCacheSize = 5;
struct PrivateD3D10DataD2D
{
RefPtr<ID3D10Effect> mEffect;
@ -122,6 +124,8 @@ public:
bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
bool InitD3D10Data();
uint32_t GetByteSize() const;
TemporaryRef<ID2D1Layer> GetCachedLayer();
void PopCachedLayer(ID2D1RenderTarget *aRT);
static ID2D1Factory *factory();
static TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions);
@ -219,6 +223,13 @@ private:
RefPtr<PathD2D> mPath;
};
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
// target is modified. We keep it alive as a cache.