Allow previously-hoisted layers to be reused in the same draw

In the Sierpinkski test case there are only a few layers appear in the "to be drawn" lists but they those layers get reused a lot of times with different transforms. This CL adds an additional category to allow such layers to be placed in the GrReplacements object without needing to be rendered.

This is split out of (Fix sub-picture layer rendering bugs - https://codereview.chromium.org/597293002/)

BUG=skia:2315
R=bsalomon@google.com

Author: robertphillips@google.com

Review URL: https://codereview.chromium.org/616023002
This commit is contained in:
robertphillips 2014-09-30 11:33:02 -07:00 committed by Commit bot
parent 5bc760a6a6
commit b5a97154f8
4 changed files with 33 additions and 16 deletions

View File

@ -18,6 +18,7 @@ bool GrLayerHoister::FindLayersToHoist(const SkPicture* topLevelPicture,
const SkRect& query,
SkTDArray<HoistedLayer>* atlased,
SkTDArray<HoistedLayer>* nonAtlased,
SkTDArray<HoistedLayer>* recycled,
GrLayerCache* layerCache) {
bool anyHoisted = false;
@ -101,20 +102,22 @@ bool GrLayerHoister::FindLayersToHoist(const SkPicture* topLevelPicture,
continue;
}
if (needsRendering) {
HoistedLayer* hl;
HoistedLayer* hl;
if (needsRendering) {
if (layer->isAtlased()) {
hl = atlased->append();
} else {
hl = nonAtlased->append();
}
hl->fLayer = layer;
hl->fPicture = pict;
hl->fOffset = info.fOffset;
hl->fCTM = info.fOriginXform;
} else {
hl = recycled->append();
}
hl->fLayer = layer;
hl->fPicture = pict;
hl->fOffset = info.fOffset;
hl->fCTM = info.fOriginXform;
}
}
@ -160,6 +163,7 @@ static void convert_layers_to_replacements(const SkTDArray<GrLayerHoister::Hoist
void GrLayerHoister::DrawLayers(const SkTDArray<HoistedLayer>& atlased,
const SkTDArray<HoistedLayer>& nonAtlased,
const SkTDArray<HoistedLayer>& recycled,
GrReplacements* replacements) {
// Render the atlased layers that require it
if (atlased.count() > 0) {
@ -253,6 +257,7 @@ void GrLayerHoister::DrawLayers(const SkTDArray<HoistedLayer>& atlased,
convert_layers_to_replacements(atlased, replacements);
convert_layers_to_replacements(nonAtlased, replacements);
convert_layers_to_replacements(recycled, replacements);
}
static void unlock_layer_in_cache(GrLayerCache* layerCache,
@ -270,7 +275,8 @@ static void unlock_layer_in_cache(GrLayerCache* layerCache,
void GrLayerHoister::UnlockLayers(GrLayerCache* layerCache,
const SkTDArray<HoistedLayer>& atlased,
const SkTDArray<HoistedLayer>& nonAtlased) {
const SkTDArray<HoistedLayer>& nonAtlased,
const SkTDArray<HoistedLayer>& recycled) {
for (int i = 0; i < atlased.count(); ++i) {
unlock_layer_in_cache(layerCache, atlased[i].fPicture, atlased[i].fLayer);
@ -280,6 +286,10 @@ void GrLayerHoister::UnlockLayers(GrLayerCache* layerCache,
unlock_layer_in_cache(layerCache, nonAtlased[i].fPicture, nonAtlased[i].fLayer);
}
for (int i = 0; i < recycled.count(); ++i) {
unlock_layer_in_cache(layerCache, recycled[i].fPicture, recycled[i].fLayer);
}
#if DISABLE_CACHING
// This code completely clears out the atlas. It is required when
// caching is disabled so the atlas doesn't fill up and force more

View File

@ -36,6 +36,7 @@ public:
@param query The rectangle that is about to be drawn.
@param atlased Out parameter storing the layers that should be hoisted to the atlas
@param nonAtlased Out parameter storing the layers that should be hoisted stand alone
@param recycled Out parameter storing layers that need hoisting but not rendering
@param layerCache The source of new layers
Return true if any layers are suitable for hoisting; false otherwise
*/
@ -43,25 +44,31 @@ public:
const SkRect& query,
SkTDArray<HoistedLayer>* altased,
SkTDArray<HoistedLayer>* nonAtlased,
SkTDArray<HoistedLayer>* recycled,
GrLayerCache* layerCache);
/** Draw the specified layers into either the atlas or free floating textures.
@param atlased The layers to be drawn into the atlas
@param nonAtlased The layers to be drawn into their own textures
@oaram replacements The replacement structure to fill in with the rendered layer info
@param recycled Layers that don't need rendering but do need to go into the
replacements object
@param replacements The replacement structure to fill in with the rendered layer info
*/
static void DrawLayers(const SkTDArray<HoistedLayer>& atlased,
const SkTDArray<HoistedLayer>& nonAtlased,
const SkTDArray<HoistedLayer>& recycled,
GrReplacements* replacements);
/** Unlock unneeded layers in the layer cache.
@param layerCache holder of the locked layers
@param atlased Unneeded layers in the atlas
@param nonAtlased Unneeded layers in their own textures
@param recycled Unneeded layers that did not require rendering
*/
static void UnlockLayers(GrLayerCache* layerCache,
const SkTDArray<HoistedLayer>& atlased,
const SkTDArray<HoistedLayer>& nonAtlased);
const SkTDArray<HoistedLayer>& nonAtlased,
const SkTDArray<HoistedLayer>& recycled);
};
#endif

View File

@ -127,8 +127,8 @@ private:
dst.fPicture->ref();
dst.fSize = SkISize::Make(newClip.width(), newClip.height());
dst.fOffset = SkIPoint::Make(newClip.fLeft, newClip.fTop);
dst.fOriginXform = *fCTM;
dst.fOriginXform.postConcat(src.fOriginXform);
dst.fOriginXform = src.fOriginXform;
dst.fOriginXform.postConcat(*fCTM);
if (src.fPaint) {
dst.fPaint = SkNEW_ARGS(SkPaint, (*src.fPaint));
}

View File

@ -1850,23 +1850,23 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
return true;
}
SkTDArray<GrLayerHoister::HoistedLayer> atlased, nonAtlased;
SkTDArray<GrLayerHoister::HoistedLayer> atlased, nonAtlased, recycled;
if (!GrLayerHoister::FindLayersToHoist(mainPicture, clipBounds, &atlased, &nonAtlased,
fContext->getLayerCache())) {
&recycled, fContext->getLayerCache())) {
return false;
}
GrReplacements replacements;
GrLayerHoister::DrawLayers(atlased, nonAtlased, &replacements);
GrLayerHoister::DrawLayers(atlased, nonAtlased, recycled, &replacements);
// Render the entire picture using new layers
const SkMatrix initialMatrix = mainCanvas->getTotalMatrix();
GrRecordReplaceDraw(mainPicture, mainCanvas, &replacements, initialMatrix, NULL);
GrLayerHoister::UnlockLayers(fContext->getLayerCache(), atlased, nonAtlased);
GrLayerHoister::UnlockLayers(fContext->getLayerCache(), atlased, nonAtlased, recycled);
return true;
}