// Atlased layers must be small enough to fit in the atlas, not have a // paint with an image filter and be neither nested nor nesting. // TODO: allow leaf nested layers to appear in the atlas. void GrLayerHoister::FindLayersToAtlas(GrContext* context, const SkPicture* topLevelPicture, const SkMatrix& initialMat, const SkRect& query, SkTDArray<GrHoistedLayer>* atlased, SkTDArray<GrHoistedLayer>* recycled, int numSamples) { if (0 != numSamples) { // MSAA layers are currently never atlased return; } GrLayerCache* layerCache = context->getLayerCache(); layerCache->processDeletedPictures(); SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); if (!topLevelData) { return; } const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData); if (0 == topLevelGPUData->numBlocks()) { return; } atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks()); for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) { const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i); // TODO: ignore perspective projected layers here? bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested || (info.fPaint && info.fPaint->getImageFilter()); if (disallowAtlasing) { continue; } SkRect layerRect; initialMat.mapRect(&layerRect, info.fBounds); if (!layerRect.intersect(query)) { continue; } const SkIRect dstIR = layerRect.roundOut(); SkIRect srcIR; if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) { continue; } prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, srcIR, dstIR, atlased, recycled, true, 0); } }
// Atlased layers must be small enough to fit in the atlas, not have a // paint with an image filter and be neither nested nor nesting. // TODO: allow leaf nested layers to appear in the atlas. void GrLayerHoister::FindLayersToAtlas(GrContext* context, const SkPicture* topLevelPicture, const SkRect& query, SkTDArray<GrHoistedLayer>* atlased, SkTDArray<GrHoistedLayer>* recycled) { GrLayerCache* layerCache = context->getLayerCache(); layerCache->processDeletedPictures(); SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); if (!topLevelData) { return; } const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData); if (0 == topLevelGPUData->numSaveLayers()) { return; } atlased->setReserve(atlased->count() + topLevelGPUData->numSaveLayers()); for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); // TODO: ignore perspective projected layers here? bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested || (info.fPaint && info.fPaint->getImageFilter()); if (disallowAtlasing) { continue; } SkRect layerRect = info.fBounds; if (!layerRect.intersect(query)) { continue; } SkIRect ir; layerRect.roundOut(&ir); if (!GrLayerCache::PlausiblyAtlasable(ir.width(), ir.height())) { continue; } prepare_for_hoisting(layerCache, topLevelPicture, info, ir, atlased, recycled, true); } }
void GrLayerHoister::FindLayersToHoist(GrContext* context, const SkPicture* topLevelPicture, const SkMatrix& initialMat, const SkRect& query, SkTDArray<GrHoistedLayer>* needRendering, SkTDArray<GrHoistedLayer>* recycled, int numSamples) { GrLayerCache* layerCache = context->getLayerCache(); layerCache->processDeletedPictures(); const SkBigPicture::AccelData* topLevelData = nullptr; if (const SkBigPicture* bp = topLevelPicture->asSkBigPicture()) { topLevelData = bp->accelData(); } if (!topLevelData) { return; } const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData); if (0 == topLevelGPUData->numBlocks()) { return; } // Find and prepare for hoisting all the layers that intersect the query rect for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) { const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i); if (info.fIsNested) { // Parent layers are currently hoisted while nested layers are not. continue; } SkRect layerRect; initialMat.mapRect(&layerRect, info.fBounds); if (!layerRect.intersect(query)) { continue; } const SkIRect dstIR = layerRect.roundOut(); SkIRect srcIR; if (!compute_source_rect(info, initialMat, dstIR, &srcIR)) { continue; } prepare_for_hoisting(layerCache, topLevelPicture, initialMat, info, srcIR, dstIR, needRendering, recycled, false, numSamples); } }
void GrLayerHoister::FindLayersToHoist(GrContext* context, const SkPicture* topLevelPicture, const SkRect& query, SkTDArray<GrHoistedLayer>* needRendering, SkTDArray<GrHoistedLayer>* recycled) { GrLayerCache* layerCache = context->getLayerCache(); layerCache->processDeletedPictures(); SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); if (!topLevelData) { return; } const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData); if (0 == topLevelGPUData->numSaveLayers()) { return; } // Find and prepare for hoisting all the layers that intersect the query rect for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); if (info.fIsNested) { // Parent layers are currently hoisted while nested layers are not. continue; } SkRect layerRect = info.fBounds; if (!layerRect.intersect(query)) { continue; } SkIRect ir; layerRect.roundOut(&ir); prepare_for_hoisting(layerCache, topLevelPicture, info, ir, needRendering, recycled, false); } }
// Return true if any layers are suitable for hoisting bool GrLayerHoister::FindLayersToHoist(GrContext* context, const SkPicture* topLevelPicture, const SkRect& query, SkTDArray<GrHoistedLayer>* atlased, SkTDArray<GrHoistedLayer>* nonAtlased, SkTDArray<GrHoistedLayer>* recycled) { GrLayerCache* layerCache = context->getLayerCache(); layerCache->processDeletedPictures(); SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); if (!topLevelData) { return false; } const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData); if (0 == topLevelGPUData->numSaveLayers()) { return false; } bool anyHoisted = false; // The layer hoisting code will pre-render and cache an entire layer if most // of it is being used (~70%) and it will fit in a texture. This is to allow // such layers to be re-used for different clips/tiles. // Small layers will additionally be atlased. // The only limitation right now is that nested layers are currently not hoisted. // Parent layers are hoisted but are never atlased (so that we never swap // away from the atlas rendertarget when generating the hoisted layers). atlased->setReserve(atlased->count() + topLevelGPUData->numSaveLayers()); // Find and prepare for hoisting all the layers that intersect the query rect for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); SkRect layerRect = SkRect::Make(info.fBounds); if (!layerRect.intersect(query)) { continue; } SkIRect ir; layerRect.roundOut(&ir); // TODO: ignore perspective projected layers here! // TODO: once this code is more stable unsuitable layers can // just be omitted during the optimization stage if (info.fIsNested) { continue; } prepare_for_hoisting(layerCache, topLevelPicture, info, ir, atlased, nonAtlased, recycled); anyHoisted = true; } return anyHoisted; }