diff options
-rw-r--r-- | gyp/core.gypi | 2 | ||||
-rw-r--r-- | gyp/gpu.gypi | 2 | ||||
-rw-r--r-- | include/core/SkPicture.h | 3 | ||||
-rw-r--r-- | src/core/SkLayerInfo.cpp (renamed from src/gpu/GrPictureUtils.cpp) | 10 | ||||
-rw-r--r-- | src/core/SkLayerInfo.h (renamed from src/gpu/GrPictureUtils.h) | 44 | ||||
-rw-r--r-- | src/core/SkPictureRecorder.cpp | 21 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 47 | ||||
-rw-r--r-- | src/core/SkRecordDraw.h | 8 | ||||
-rw-r--r-- | src/gpu/GrLayerCache.h | 4 | ||||
-rw-r--r-- | src/gpu/GrLayerHoister.cpp | 25 | ||||
-rw-r--r-- | src/gpu/GrLayerHoister.h | 1 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 5 | ||||
-rw-r--r-- | tests/PictureTest.cpp | 384 |
13 files changed, 251 insertions, 305 deletions
diff --git a/gyp/core.gypi b/gyp/core.gypi index 120a63525a..abd4a5cd77 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -105,6 +105,8 @@ '<(skia_src_path)/core/SkImageFilter.cpp', '<(skia_src_path)/core/SkImageInfo.cpp', '<(skia_src_path)/core/SkImageGenerator.cpp', + '<(skia_src_path)/core/SkLayerInfo.h', + '<(skia_src_path)/core/SkLayerInfo.cpp', '<(skia_src_path)/core/SkLocalMatrixShader.cpp', '<(skia_src_path)/core/SkLineClipper.cpp', '<(skia_src_path)/core/SkMallocPixelRef.cpp', diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 2cf380b996..430bac9dd7 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -123,8 +123,6 @@ '<(skia_src_path)/gpu/GrProgramElement.cpp', '<(skia_src_path)/gpu/GrProcessor.cpp', '<(skia_src_path)/gpu/GrGpuResourceRef.cpp', - '<(skia_src_path)/gpu/GrPictureUtils.h', - '<(skia_src_path)/gpu/GrPictureUtils.cpp', '<(skia_src_path)/gpu/GrPlotMgr.h', '<(skia_src_path)/gpu/GrRecordReplaceDraw.cpp', '<(skia_src_path)/gpu/GrRecordReplaceDraw.h', diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index 41d5c1cdb0..4bef2b0d2f 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -46,8 +46,7 @@ public: SK_DECLARE_INST_COUNT(SkPicture) // AccelData provides a base class for device-specific acceleration - // data. It is added to the picture via a call to a device's optimize - // method. + // data. It is added to the picture via EXPERIMENTAL_addAccelData. class AccelData : public SkRefCnt { public: typedef uint8_t Domain; diff --git a/src/gpu/GrPictureUtils.cpp b/src/core/SkLayerInfo.cpp index e8e965bb57..d427fa7c21 100644 --- a/src/gpu/GrPictureUtils.cpp +++ b/src/core/SkLayerInfo.cpp @@ -5,15 +5,9 @@ * found in the LICENSE file. */ -#include "GrPictureUtils.h" +#include "SkLayerInfo.h" -#include "SkBBoxHierarchy.h" -#include "SkPaintPriv.h" -#include "SkPatchUtils.h" -#include "SkRecord.h" -#include "SkRecords.h" - -SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() { +SkPicture::AccelData::Key SkLayerInfo::ComputeKey() { static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain(); return gGPUID; diff --git a/src/gpu/GrPictureUtils.h b/src/core/SkLayerInfo.h index f24910507d..dd0eaf032a 100644 --- a/src/gpu/GrPictureUtils.h +++ b/src/core/SkLayerInfo.h @@ -5,24 +5,24 @@ * found in the LICENSE file. */ -#ifndef GrPictureUtils_DEFINED -#define GrPictureUtils_DEFINED +#ifndef SkLayerInfo_DEFINED +#define SkLayerInfo_DEFINED #include "SkPicture.h" #include "SkTArray.h" -// This class encapsulates the GPU-backend-specific acceleration data -// for a single SkPicture -class GrAccelData : public SkPicture::AccelData { +// This class stores information about the saveLayer/restore pairs found +// within an SkPicture. It is used by Ganesh to perform layer hoisting. +class SkLayerInfo : public SkPicture::AccelData { public: - // Information about a given saveLayer in an SkPicture - class SaveLayerInfo { + // Information about a given saveLayer/restore block in an SkPicture + class BlockInfo { public: - SaveLayerInfo() : fPicture(NULL), fPaint(NULL) {} - ~SaveLayerInfo() { SkSafeUnref(fPicture); SkDELETE(fPaint); } + BlockInfo() : fPicture(NULL), fPaint(NULL) {} + ~BlockInfo() { SkSafeUnref(fPicture); SkDELETE(fPaint); } // The picture owning the layer. If the owning picture is the top-most - // one (i.e., the picture for which this GrAccelData was created) then + // one (i.e., the picture for which this SkLayerInfo was created) then // this pointer is NULL. If it is a nested picture then the pointer // is non-NULL and owns a ref on the picture. const SkPicture* fPicture; @@ -41,9 +41,9 @@ public: SkMatrix fLocalMat; // The paint to use on restore. Can be NULL since it is optional. const SkPaint* fPaint; - // The ID of this saveLayer in the picture. 0 is an invalid ID. + // The index of this saveLayer in the picture. size_t fSaveLayerOpID; - // The ID of the matching restore in the picture. 0 is an invalid ID. + // The index of the matching restore in the picture. size_t fRestoreOpID; // True if this saveLayer has at least one other saveLayer nested within it. // False otherwise. @@ -52,28 +52,26 @@ public: bool fIsNested; }; - GrAccelData(Key key) : INHERITED(key) { } + SkLayerInfo(Key key) : INHERITED(key) { } - virtual ~GrAccelData() { } + BlockInfo& addBlock() { return fBlocks.push_back(); } - SaveLayerInfo& addSaveLayerInfo() { return fSaveLayerInfo.push_back(); } + int numBlocks() const { return fBlocks.count(); } - int numSaveLayers() const { return fSaveLayerInfo.count(); } + const BlockInfo& block(int index) const { + SkASSERT(index < fBlocks.count()); - const SaveLayerInfo& saveLayerInfo(int index) const { - SkASSERT(index < fSaveLayerInfo.count()); - - return fSaveLayerInfo[index]; + return fBlocks[index]; } // We may, in the future, need to pass in the GPUDevice in order to // incorporate the clip and matrix state into the key - static SkPicture::AccelData::Key ComputeAccelDataKey(); + static SkPicture::AccelData::Key ComputeKey(); private: - SkTArray<SaveLayerInfo, true> fSaveLayerInfo; + SkTArray<BlockInfo, true> fBlocks; typedef SkPicture::AccelData INHERITED; }; -#endif // GrPictureUtils_DEFINED +#endif // SkLayerInfo_DEFINED diff --git a/src/core/SkPictureRecorder.cpp b/src/core/SkPictureRecorder.cpp index 160446797d..3441a0dfeb 100644 --- a/src/core/SkPictureRecorder.cpp +++ b/src/core/SkPictureRecorder.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "SkLayerInfo.h" #include "SkPictureRecorder.h" #include "SkRecord.h" #include "SkRecordDraw.h" @@ -12,12 +13,6 @@ #include "SkRecordOpts.h" #include "SkTypes.h" -// Must place SK_SUPPORT_GPU after other includes so it is defined in the -// Android framework build. -#if SK_SUPPORT_GPU -#include "GrPictureUtils.h" -#endif - SkPictureRecorder::SkPictureRecorder() {} SkPictureRecorder::~SkPictureRecorder() {} @@ -47,37 +42,29 @@ SkPicture* SkPictureRecorder::endRecording() { // TODO: delay as much of this work until just before first playback? SkRecordOptimize(fRecord); -#if SK_SUPPORT_GPU - SkAutoTUnref<GrAccelData> saveLayerData; + SkAutoTUnref<SkLayerInfo> saveLayerData; if (fBBH && (fFlags & kComputeSaveLayerInfo_RecordFlag)) { - SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); + SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); - saveLayerData.reset(SkNEW_ARGS(GrAccelData, (key))); + saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key))); } -#endif if (fBBH.get()) { SkRect cullRect = SkRect::MakeWH(fCullWidth, fCullHeight); -#if SK_SUPPORT_GPU if (saveLayerData) { SkRecordComputeLayers(cullRect, *fRecord, fBBH.get(), saveLayerData); } else { -#endif SkRecordFillBounds(cullRect, *fRecord, fBBH.get()); -#if SK_SUPPORT_GPU } -#endif } SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullWidth, fCullHeight, fRecord.detach(), fBBH.get())); -#if SK_SUPPORT_GPU if (saveLayerData) { pict->EXPERIMENTAL_addAccelData(saveLayerData); } -#endif return pict; } diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 9075e508f7..e35e5a0a9d 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -5,13 +5,10 @@ * found in the LICENSE file. */ +#include "SkLayerInfo.h" #include "SkRecordDraw.h" #include "SkPatchUtils.h" -#if SK_SUPPORT_GPU -#include "GrPictureUtils.h" -#endif - void SkRecordDraw(const SkRecord& record, SkCanvas* canvas, const SkBBoxHierarchy* bbh, @@ -570,11 +567,10 @@ private: SkTDArray<unsigned> fControlIndices; }; -#if SK_SUPPORT_GPU // SkRecord visitor to gather saveLayer/restore information. class CollectLayers : SkNoncopyable { public: - CollectLayers(const SkRect& cullRect, const SkRecord& record, GrAccelData* accelData) + CollectLayers(const SkRect& cullRect, const SkRecord& record, SkLayerInfo* accelData) : fSaveLayersInStack(0) , fAccelData(accelData) , fFillBounds(cullRect, record) { @@ -624,10 +620,10 @@ private: void trackSaveLayers(const DrawPicture& dp) { // For sub-pictures, we wrap their layer information within the parent // picture's rendering hierarchy - SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); + SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); - const GrAccelData* childData = - static_cast<const GrAccelData*>(dp.picture->EXPERIMENTAL_getAccelData(key)); + const SkLayerInfo* childData = + static_cast<const SkLayerInfo*>(dp.picture->EXPERIMENTAL_getAccelData(key)); if (!childData) { // If the child layer hasn't been generated with saveLayer data we // assume the worst (i.e., that it does contain layers which nest @@ -638,8 +634,8 @@ private: return; } - for (int i = 0; i < childData->numSaveLayers(); ++i) { - const GrAccelData::SaveLayerInfo& src = childData->saveLayerInfo(i); + for (int i = 0; i < childData->numBlocks(); ++i) { + const SkLayerInfo::BlockInfo& src = childData->block(i); FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds, dp.paint); if (newBound.isEmpty()) { @@ -648,7 +644,7 @@ private: this->updateStackForSaveLayer(); - GrAccelData::SaveLayerInfo& dst = fAccelData->addSaveLayerInfo(); + SkLayerInfo::BlockInfo& dst = fAccelData->addBlock(); // If src.fPicture is NULL the layer is in dp.picture; otherwise // it belongs to a sub-picture. @@ -706,30 +702,29 @@ private: --fSaveLayersInStack; - GrAccelData::SaveLayerInfo& slInfo = fAccelData->addSaveLayerInfo(); + SkLayerInfo::BlockInfo& block = fAccelData->addBlock(); - SkASSERT(NULL == slInfo.fPicture); // This layer is in the top-most picture + SkASSERT(NULL == block.fPicture); // This layer is in the top-most picture - slInfo.fBounds = fFillBounds.getBounds(sli.fStartIndex); - slInfo.fLocalMat = fFillBounds.ctm(); - slInfo.fPreMat = SkMatrix::I(); + block.fBounds = fFillBounds.getBounds(sli.fStartIndex); + block.fLocalMat = fFillBounds.ctm(); + block.fPreMat = SkMatrix::I(); if (sli.fPaint) { - slInfo.fPaint = SkNEW_ARGS(SkPaint, (*sli.fPaint)); + block.fPaint = SkNEW_ARGS(SkPaint, (*sli.fPaint)); } - slInfo.fSaveLayerOpID = sli.fStartIndex; - slInfo.fRestoreOpID = fFillBounds.currentOp(); - slInfo.fHasNestedLayers = sli.fHasNestedSaveLayer; - slInfo.fIsNested = fSaveLayersInStack > 0; + block.fSaveLayerOpID = sli.fStartIndex; + block.fRestoreOpID = fFillBounds.currentOp(); + block.fHasNestedLayers = sli.fHasNestedSaveLayer; + block.fIsNested = fSaveLayersInStack > 0; } // Used to collect saveLayer information for layer hoisting int fSaveLayersInStack; SkTDArray<SaveLayerInfo> fSaveLayerStack; - GrAccelData* fAccelData; + SkLayerInfo* fAccelData; SkRecords::FillBounds fFillBounds; }; -#endif } // namespace SkRecords @@ -744,9 +739,8 @@ void SkRecordFillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHi visitor.cleanUp(bbh); } -#if SK_SUPPORT_GPU void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record, - SkBBoxHierarchy* bbh, GrAccelData* data) { + SkBBoxHierarchy* bbh, SkLayerInfo* data) { SkRecords::CollectLayers visitor(cullRect, record, data); for (unsigned curOp = 0; curOp < record.count(); curOp++) { @@ -756,5 +750,4 @@ void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record, visitor.cleanUp(bbh); } -#endif diff --git a/src/core/SkRecordDraw.h b/src/core/SkRecordDraw.h index 8df64cbecd..9b39dd6adb 100644 --- a/src/core/SkRecordDraw.h +++ b/src/core/SkRecordDraw.h @@ -14,15 +14,13 @@ #include "SkMatrix.h" #include "SkRecord.h" +class SkLayerInfo; + // Fill a BBH to be used by SkRecordDraw to accelerate playback. void SkRecordFillBounds(const SkRect& cullRect, const SkRecord&, SkBBoxHierarchy*); -#if SK_SUPPORT_GPU -class GrAccelData; - void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record, - SkBBoxHierarchy* bbh, GrAccelData* data); -#endif + SkBBoxHierarchy* bbh, SkLayerInfo* data); // Draw an SkRecord into an SkCanvas. A convenience wrapper around SkRecords::Draw. void SkRecordDraw(const SkRecord&, SkCanvas*, const SkBBoxHierarchy*, SkDrawPictureCallback*); diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h index 69b59cf747..8dec8e594d 100644 --- a/src/gpu/GrLayerCache.h +++ b/src/gpu/GrLayerCache.h @@ -9,15 +9,13 @@ #define GrLayerCache_DEFINED #include "GrAtlas.h" -#include "GrPictureUtils.h" #include "GrRect.h" #include "SkChecksum.h" #include "SkMessageBus.h" +#include "SkPicture.h" #include "SkTDynamicHash.h" -class SkPicture; - // Set to 0 to disable caching of hoisted layers #define GR_CACHE_HOISTED_LAYERS 0 diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp index c74913d757..bc635aea07 100644 --- a/src/gpu/GrLayerHoister.cpp +++ b/src/gpu/GrLayerHoister.cpp @@ -11,6 +11,7 @@ #include "SkCanvas.h" #include "SkGrPixelRef.h" +#include "SkLayerInfo.h" #include "SkRecordDraw.h" #include "SkSurface.h" @@ -18,7 +19,7 @@ // required texture/render target resources. static void prepare_for_hoisting(GrLayerCache* layerCache, const SkPicture* topLevelPicture, - const GrAccelData::SaveLayerInfo& info, + const SkLayerInfo::BlockInfo& info, const SkIRect& layerRect, SkTDArray<GrHoistedLayer>* needRendering, SkTDArray<GrHoistedLayer>* recycled, @@ -93,22 +94,22 @@ void GrLayerHoister::FindLayersToAtlas(GrContext* context, layerCache->processDeletedPictures(); - SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); + SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); if (!topLevelData) { return; } - const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData); - if (0 == topLevelGPUData->numSaveLayers()) { + const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData); + if (0 == topLevelGPUData->numBlocks()) { return; } - atlased->setReserve(atlased->count() + topLevelGPUData->numSaveLayers()); + atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks()); - for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) { - const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); + 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 || @@ -145,21 +146,21 @@ void GrLayerHoister::FindLayersToHoist(GrContext* context, layerCache->processDeletedPictures(); - SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); + SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key); if (!topLevelData) { return; } - const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData); - if (0 == topLevelGPUData->numSaveLayers()) { + 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->numSaveLayers(); ++i) { - const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i); + 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; diff --git a/src/gpu/GrLayerHoister.h b/src/gpu/GrLayerHoister.h index 0780c1e801..12d8a842a0 100644 --- a/src/gpu/GrLayerHoister.h +++ b/src/gpu/GrLayerHoister.h @@ -11,7 +11,6 @@ #include "SkPicture.h" #include "SkTDArray.h" -class GrAccelData; struct GrCachedLayer; class GrReplacements; struct SkRect; diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 06f6eb7778..124f994612 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -15,9 +15,7 @@ #include "GrContext.h" #include "GrBitmapTextContext.h" #include "GrDistanceFieldTextContext.h" -#include "GrLayerCache.h" #include "GrLayerHoister.h" -#include "GrPictureUtils.h" #include "GrRecordReplaceDraw.h" #include "GrStrokeInfo.h" #include "GrTracing.h" @@ -29,6 +27,7 @@ #include "SkDrawProcs.h" #include "SkGlyphCache.h" #include "SkImageFilter.h" +#include "SkLayerInfo.h" #include "SkMaskFilter.h" #include "SkPathEffect.h" #include "SkPicture.h" @@ -1796,7 +1795,7 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture return false; } - SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); + SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); const SkPicture::AccelData* data = mainPicture->EXPERIMENTAL_getAccelData(key); if (!data) { diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp index 3cb145e7a4..5bc60371c9 100644 --- a/tests/PictureTest.cpp +++ b/tests/PictureTest.cpp @@ -16,6 +16,7 @@ #include "SkError.h" #include "SkImageEncoder.h" #include "SkImageGenerator.h" +#include "SkLayerInfo.h" #include "SkPaint.h" #include "SkPicture.h" #include "SkPictureRecorder.h" @@ -29,7 +30,6 @@ #if SK_SUPPORT_GPU #include "SkSurface.h" #include "GrContextFactory.h" -#include "GrPictureUtils.h" #endif #include "Test.h" @@ -871,224 +871,209 @@ static void test_gpu_veto(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(NULL)); } -static void test_gpu_picture_optimization(skiatest::Reporter* reporter, - GrContextFactory* factory) { - for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) { - GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i; +#endif - if (!GrContextFactory::IsRenderingGLContext(glCtxType)) { - continue; - } +static void test_savelayer_extraction(skiatest::Reporter* reporter) { + static const int kWidth = 100; + static const int kHeight = 100; - GrContext* context = factory->get(glCtxType); + // Create complex paint that the bounding box computation code can't + // optimize away + SkScalar blueToRedMatrix[20] = { 0 }; + blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1; + SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix)); + SkAutoTUnref<SkImageFilter> filter(SkColorFilterImageFilter::Create(blueToRed.get())); - if (NULL == context) { - continue; - } + SkPaint complexPaint; + complexPaint.setImageFilter(filter); - static const int kWidth = 100; - static const int kHeight = 100; + SkAutoTUnref<SkPicture> pict, child; + SkRTreeFactory bbhFactory; - // Create complex paint that the bounding box computation code can't - // optimize away - SkScalar blueToRedMatrix[20] = { 0 }; - blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1; - SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix)); - SkAutoTUnref<SkImageFilter> filter(SkColorFilterImageFilter::Create(blueToRed.get())); + { + SkPictureRecorder recorder; - SkPaint complexPaint; - complexPaint.setImageFilter(filter); + SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight), + &bbhFactory, + SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); - SkAutoTUnref<SkPicture> pict, child; - SkRTreeFactory bbhFactory; + c->saveLayer(NULL, &complexPaint); + c->restore(); - { - SkPictureRecorder recorder; + child.reset(recorder.endRecording()); + } - SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight), - &bbhFactory, - SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); + // create a picture with the structure: + // 1) + // SaveLayer + // Restore + // 2) + // SaveLayer + // Translate + // SaveLayer w/ bound + // Restore + // Restore + // 3) + // SaveLayer w/ copyable paint + // Restore + // 4) + // SaveLayer + // DrawPicture (which has a SaveLayer/Restore pair) + // Restore + // 5) + // SaveLayer + // DrawPicture with Matrix & Paint (with SaveLayer/Restore pair) + // Restore + { + SkPictureRecorder recorder; - c->saveLayer(NULL, &complexPaint); + SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), + SkIntToScalar(kHeight), + &bbhFactory, + SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); + // 1) + c->saveLayer(NULL, &complexPaint); // layer #0 + c->restore(); + + // 2) + c->saveLayer(NULL, NULL); // layer #1 + c->translate(kWidth/2.0f, kHeight/2.0f); + SkRect r = SkRect::MakeXYWH(0, 0, kWidth/2, kHeight/2); + c->saveLayer(&r, &complexPaint); // layer #2 c->restore(); + c->restore(); - child.reset(recorder.endRecording()); + // 3) + { + c->saveLayer(NULL, &complexPaint); // layer #3 + c->restore(); } - // create a picture with the structure: - // 1) - // SaveLayer - // Restore - // 2) - // SaveLayer - // Translate - // SaveLayer w/ bound - // Restore - // Restore - // 3) - // SaveLayer w/ copyable paint - // Restore + SkPaint layerPaint; + layerPaint.setColor(SK_ColorRED); // Non-alpha only to avoid SaveLayerDrawRestoreNooper // 4) - // SaveLayer - // DrawPicture (which has a SaveLayer/Restore pair) - // Restore - // 5) - // SaveLayer - // DrawPicture with Matrix & Paint (with SaveLayer/Restore pair) - // Restore { - SkPictureRecorder recorder; - - SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), - SkIntToScalar(kHeight), - &bbhFactory, - SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); - // 1) - c->saveLayer(NULL, &complexPaint); // layer #0 + c->saveLayer(NULL, &layerPaint); // layer #4 + c->drawPicture(child); // layer #5 inside picture c->restore(); + } + // 5 + { + SkPaint picturePaint; + SkMatrix trans; + trans.setTranslate(10, 10); - // 2) - c->saveLayer(NULL, NULL); // layer #1 - c->translate(kWidth/2.0f, kHeight/2.0f); - SkRect r = SkRect::MakeXYWH(0, 0, kWidth/2, kHeight/2); - c->saveLayer(&r, &complexPaint); // layer #2 - c->restore(); + c->saveLayer(NULL, &layerPaint); // layer #6 + c->drawPicture(child, &trans, &picturePaint); // layer #7 inside picture c->restore(); - - // 3) - { - c->saveLayer(NULL, &complexPaint); // layer #3 - c->restore(); - } - - SkPaint layerPaint; - layerPaint.setColor(SK_ColorRED); // Non-alpha only to avoid SaveLayerDrawRestoreNooper - // 4) - { - c->saveLayer(NULL, &layerPaint); // layer #4 - c->drawPicture(child); // layer #5 inside picture - c->restore(); - } - // 5 - { - SkPaint picturePaint; - SkMatrix trans; - trans.setTranslate(10, 10); - - c->saveLayer(NULL, &layerPaint); // layer #6 - c->drawPicture(child, &trans, &picturePaint); // layer #7 inside picture - c->restore(); - } - - pict.reset(recorder.endRecording()); } - // Now test out the SaveLayer extraction - { - SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey(); - - const SkPicture::AccelData* data = pict->EXPERIMENTAL_getAccelData(key); - REPORTER_ASSERT(reporter, data); - - const GrAccelData *gpuData = static_cast<const GrAccelData*>(data); - REPORTER_ASSERT(reporter, 8 == gpuData->numSaveLayers()); - - const GrAccelData::SaveLayerInfo& info0 = gpuData->saveLayerInfo(0); - // The parent/child layers appear in reverse order - const GrAccelData::SaveLayerInfo& info1 = gpuData->saveLayerInfo(2); - const GrAccelData::SaveLayerInfo& info2 = gpuData->saveLayerInfo(1); - - const GrAccelData::SaveLayerInfo& info3 = gpuData->saveLayerInfo(3); - - // The parent/child layers appear in reverse order - const GrAccelData::SaveLayerInfo& info4 = gpuData->saveLayerInfo(5); - const GrAccelData::SaveLayerInfo& info5 = gpuData->saveLayerInfo(4); - - // The parent/child layers appear in reverse order - const GrAccelData::SaveLayerInfo& info6 = gpuData->saveLayerInfo(7); - const GrAccelData::SaveLayerInfo& info7 = gpuData->saveLayerInfo(6); - - REPORTER_ASSERT(reporter, NULL == info0.fPicture); - REPORTER_ASSERT(reporter, kWidth == info0.fBounds.width() && - kHeight == info0.fBounds.height()); - REPORTER_ASSERT(reporter, info0.fLocalMat.isIdentity()); - REPORTER_ASSERT(reporter, info0.fPreMat.isIdentity()); - REPORTER_ASSERT(reporter, 0 == info0.fBounds.fLeft && 0 == info0.fBounds.fTop); - REPORTER_ASSERT(reporter, NULL != info0.fPaint); - REPORTER_ASSERT(reporter, !info0.fIsNested && !info0.fHasNestedLayers); - - REPORTER_ASSERT(reporter, NULL == info1.fPicture); - REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.width() && - kHeight/2.0 == info1.fBounds.height()); - REPORTER_ASSERT(reporter, info1.fLocalMat.isIdentity()); - REPORTER_ASSERT(reporter, info1.fPreMat.isIdentity()); - REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.fLeft && - kHeight/2.0 == info1.fBounds.fTop); - REPORTER_ASSERT(reporter, NULL == info1.fPaint); - REPORTER_ASSERT(reporter, !info1.fIsNested && - info1.fHasNestedLayers); // has a nested SL - - REPORTER_ASSERT(reporter, NULL == info2.fPicture); - REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.width() && - kHeight / 2 == info2.fBounds.height()); // bound reduces size - REPORTER_ASSERT(reporter, !info2.fLocalMat.isIdentity()); - REPORTER_ASSERT(reporter, info2.fPreMat.isIdentity()); - REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.fLeft && // translated - kHeight / 2 == info2.fBounds.fTop); - REPORTER_ASSERT(reporter, NULL != info2.fPaint); - REPORTER_ASSERT(reporter, info2.fIsNested && !info2.fHasNestedLayers); // is nested - - REPORTER_ASSERT(reporter, NULL == info3.fPicture); - REPORTER_ASSERT(reporter, kWidth == info3.fBounds.width() && - kHeight == info3.fBounds.height()); - REPORTER_ASSERT(reporter, info3.fLocalMat.isIdentity()); - REPORTER_ASSERT(reporter, info3.fPreMat.isIdentity()); - REPORTER_ASSERT(reporter, 0 == info3.fBounds.fLeft && 0 == info3.fBounds.fTop); - REPORTER_ASSERT(reporter, info3.fPaint); - REPORTER_ASSERT(reporter, !info3.fIsNested && !info3.fHasNestedLayers); - - REPORTER_ASSERT(reporter, NULL == info4.fPicture); - REPORTER_ASSERT(reporter, kWidth == info4.fBounds.width() && - kHeight == info4.fBounds.height()); - REPORTER_ASSERT(reporter, 0 == info4.fBounds.fLeft && 0 == info4.fBounds.fTop); - REPORTER_ASSERT(reporter, info4.fLocalMat.isIdentity()); - REPORTER_ASSERT(reporter, info4.fPreMat.isIdentity()); - REPORTER_ASSERT(reporter, info4.fPaint); - REPORTER_ASSERT(reporter, !info4.fIsNested && - info4.fHasNestedLayers); // has a nested SL - - REPORTER_ASSERT(reporter, child == info5.fPicture); // in a child picture - REPORTER_ASSERT(reporter, kWidth == info5.fBounds.width() && - kHeight == info5.fBounds.height()); - REPORTER_ASSERT(reporter, 0 == info5.fBounds.fLeft && 0 == info5.fBounds.fTop); - REPORTER_ASSERT(reporter, info5.fLocalMat.isIdentity()); - REPORTER_ASSERT(reporter, info5.fPreMat.isIdentity()); - REPORTER_ASSERT(reporter, NULL != info5.fPaint); - REPORTER_ASSERT(reporter, info5.fIsNested && !info5.fHasNestedLayers); // is nested - - REPORTER_ASSERT(reporter, NULL == info6.fPicture); - REPORTER_ASSERT(reporter, kWidth-10 == info6.fBounds.width() && - kHeight-10 == info6.fBounds.height()); - REPORTER_ASSERT(reporter, 10 == info6.fBounds.fLeft && 10 == info6.fBounds.fTop); - REPORTER_ASSERT(reporter, info6.fLocalMat.isIdentity()); - REPORTER_ASSERT(reporter, info6.fPreMat.isIdentity()); - REPORTER_ASSERT(reporter, info6.fPaint); - REPORTER_ASSERT(reporter, !info6.fIsNested && - info6.fHasNestedLayers); // has a nested SL - - REPORTER_ASSERT(reporter, child == info7.fPicture); // in a child picture - REPORTER_ASSERT(reporter, kWidth == info7.fBounds.width() && - kHeight == info7.fBounds.height()); - REPORTER_ASSERT(reporter, 0 == info7.fBounds.fLeft && 0 == info7.fBounds.fTop); - REPORTER_ASSERT(reporter, info7.fLocalMat.isIdentity()); - REPORTER_ASSERT(reporter, info7.fPreMat.isIdentity()); - REPORTER_ASSERT(reporter, NULL != info7.fPaint); - REPORTER_ASSERT(reporter, info7.fIsNested && !info7.fHasNestedLayers); // is nested - } + pict.reset(recorder.endRecording()); } -} -#endif + // Now test out the SaveLayer extraction + { + SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); + + const SkPicture::AccelData* data = pict->EXPERIMENTAL_getAccelData(key); + REPORTER_ASSERT(reporter, data); + + const SkLayerInfo *gpuData = static_cast<const SkLayerInfo*>(data); + REPORTER_ASSERT(reporter, 8 == gpuData->numBlocks()); + + const SkLayerInfo::BlockInfo& info0 = gpuData->block(0); + // The parent/child layers appear in reverse order + const SkLayerInfo::BlockInfo& info1 = gpuData->block(2); + const SkLayerInfo::BlockInfo& info2 = gpuData->block(1); + + const SkLayerInfo::BlockInfo& info3 = gpuData->block(3); + + // The parent/child layers appear in reverse order + const SkLayerInfo::BlockInfo& info4 = gpuData->block(5); + const SkLayerInfo::BlockInfo& info5 = gpuData->block(4); + + // The parent/child layers appear in reverse order + const SkLayerInfo::BlockInfo& info6 = gpuData->block(7); + const SkLayerInfo::BlockInfo& info7 = gpuData->block(6); + + REPORTER_ASSERT(reporter, NULL == info0.fPicture); + REPORTER_ASSERT(reporter, kWidth == info0.fBounds.width() && + kHeight == info0.fBounds.height()); + REPORTER_ASSERT(reporter, info0.fLocalMat.isIdentity()); + REPORTER_ASSERT(reporter, info0.fPreMat.isIdentity()); + REPORTER_ASSERT(reporter, 0 == info0.fBounds.fLeft && 0 == info0.fBounds.fTop); + REPORTER_ASSERT(reporter, NULL != info0.fPaint); + REPORTER_ASSERT(reporter, !info0.fIsNested && !info0.fHasNestedLayers); + + REPORTER_ASSERT(reporter, NULL == info1.fPicture); + REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.width() && + kHeight/2.0 == info1.fBounds.height()); + REPORTER_ASSERT(reporter, info1.fLocalMat.isIdentity()); + REPORTER_ASSERT(reporter, info1.fPreMat.isIdentity()); + REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.fLeft && + kHeight/2.0 == info1.fBounds.fTop); + REPORTER_ASSERT(reporter, NULL == info1.fPaint); + REPORTER_ASSERT(reporter, !info1.fIsNested && + info1.fHasNestedLayers); // has a nested SL + + REPORTER_ASSERT(reporter, NULL == info2.fPicture); + REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.width() && + kHeight / 2 == info2.fBounds.height()); // bound reduces size + REPORTER_ASSERT(reporter, !info2.fLocalMat.isIdentity()); + REPORTER_ASSERT(reporter, info2.fPreMat.isIdentity()); + REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.fLeft && // translated + kHeight / 2 == info2.fBounds.fTop); + REPORTER_ASSERT(reporter, NULL != info2.fPaint); + REPORTER_ASSERT(reporter, info2.fIsNested && !info2.fHasNestedLayers); // is nested + + REPORTER_ASSERT(reporter, NULL == info3.fPicture); + REPORTER_ASSERT(reporter, kWidth == info3.fBounds.width() && + kHeight == info3.fBounds.height()); + REPORTER_ASSERT(reporter, info3.fLocalMat.isIdentity()); + REPORTER_ASSERT(reporter, info3.fPreMat.isIdentity()); + REPORTER_ASSERT(reporter, 0 == info3.fBounds.fLeft && 0 == info3.fBounds.fTop); + REPORTER_ASSERT(reporter, info3.fPaint); + REPORTER_ASSERT(reporter, !info3.fIsNested && !info3.fHasNestedLayers); + + REPORTER_ASSERT(reporter, NULL == info4.fPicture); + REPORTER_ASSERT(reporter, kWidth == info4.fBounds.width() && + kHeight == info4.fBounds.height()); + REPORTER_ASSERT(reporter, 0 == info4.fBounds.fLeft && 0 == info4.fBounds.fTop); + REPORTER_ASSERT(reporter, info4.fLocalMat.isIdentity()); + REPORTER_ASSERT(reporter, info4.fPreMat.isIdentity()); + REPORTER_ASSERT(reporter, info4.fPaint); + REPORTER_ASSERT(reporter, !info4.fIsNested && + info4.fHasNestedLayers); // has a nested SL + + REPORTER_ASSERT(reporter, child == info5.fPicture); // in a child picture + REPORTER_ASSERT(reporter, kWidth == info5.fBounds.width() && + kHeight == info5.fBounds.height()); + REPORTER_ASSERT(reporter, 0 == info5.fBounds.fLeft && 0 == info5.fBounds.fTop); + REPORTER_ASSERT(reporter, info5.fLocalMat.isIdentity()); + REPORTER_ASSERT(reporter, info5.fPreMat.isIdentity()); + REPORTER_ASSERT(reporter, NULL != info5.fPaint); + REPORTER_ASSERT(reporter, info5.fIsNested && !info5.fHasNestedLayers); // is nested + + REPORTER_ASSERT(reporter, NULL == info6.fPicture); + REPORTER_ASSERT(reporter, kWidth-10 == info6.fBounds.width() && + kHeight-10 == info6.fBounds.height()); + REPORTER_ASSERT(reporter, 10 == info6.fBounds.fLeft && 10 == info6.fBounds.fTop); + REPORTER_ASSERT(reporter, info6.fLocalMat.isIdentity()); + REPORTER_ASSERT(reporter, info6.fPreMat.isIdentity()); + REPORTER_ASSERT(reporter, info6.fPaint); + REPORTER_ASSERT(reporter, !info6.fIsNested && + info6.fHasNestedLayers); // has a nested SL + + REPORTER_ASSERT(reporter, child == info7.fPicture); // in a child picture + REPORTER_ASSERT(reporter, kWidth == info7.fBounds.width() && + kHeight == info7.fBounds.height()); + REPORTER_ASSERT(reporter, 0 == info7.fBounds.fLeft && 0 == info7.fBounds.fTop); + REPORTER_ASSERT(reporter, info7.fLocalMat.isIdentity()); + REPORTER_ASSERT(reporter, info7.fPreMat.isIdentity()); + REPORTER_ASSERT(reporter, NULL != info7.fPaint); + REPORTER_ASSERT(reporter, info7.fIsNested && !info7.fHasNestedLayers); // is nested + } +} static void test_has_text(skiatest::Reporter* reporter) { SkPictureRecorder recorder; @@ -1757,14 +1742,9 @@ DEF_TEST(Picture, reporter) { test_clip_expansion(reporter); test_hierarchical(reporter); test_gen_id(reporter); + test_savelayer_extraction(reporter); } -#if SK_SUPPORT_GPU -DEF_GPUTEST(GPUPicture, reporter, factory) { - test_gpu_picture_optimization(reporter, factory); -} -#endif - static void draw_bitmaps(const SkBitmap bitmap, SkCanvas* canvas) { const SkPaint paint; const SkRect rect = { 5.0f, 5.0f, 8.0f, 8.0f }; |