Skip to content

Commit

Permalink
Bug 761397 - Part 1: Cache ID2D1Layers for D2D Azure backend. r=jrmuizel
Browse files Browse the repository at this point in the history
  • Loading branch information
Bas-moz committed Jun 20, 2012
1 parent 5e22a78 commit b06e5bf
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 9 deletions.
52 changes: 43 additions & 9 deletions gfx/2d/DrawTargetD2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ class AutoSaveRestoreClippedOut
};

DrawTargetD2D::DrawTargetD2D()
: mClipsArePushed(false)
: mCurrentCachedLayer(0)
, mClipsArePushed(false)
, mPrivateData(NULL)
{
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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(),
Expand All @@ -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));
}
Expand All @@ -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
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -1015,7 +1023,7 @@ DrawTargetD2D::PopClip()
mCurrentClippedGeometry = NULL;
if (mClipsArePushed) {
if (mPushedClips.back().mLayer) {
mRT->PopLayer();
PopCachedLayer(mRT);
} else {
mRT->PopAxisAlignedClip();
}
Expand Down Expand Up @@ -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()
{
Expand Down
11 changes: 11 additions & 0 deletions gfx/2d/DrawTargetD2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class SourceSurfaceD2D;
class GradientStopsD2D;
class ScaledFontDWrite;

const int32_t kLayerCacheSize = 5;

struct PrivateD3D10DataD2D
{
RefPtr<ID3D10Effect> mEffect;
Expand Down Expand Up @@ -122,6 +124,8 @@ class DrawTargetD2D : public DrawTarget
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);
Expand Down Expand Up @@ -219,6 +223,13 @@ class DrawTargetD2D : public DrawTarget
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.
Expand Down

0 comments on commit b06e5bf

Please sign in to comment.