diff options
-rw-r--r-- | include/core/SkPictureRecorder.h | 6 | ||||
-rw-r--r-- | include/private/SkRecords.h | 47 | ||||
-rw-r--r-- | src/core/SkPictureCommon.h | 10 | ||||
-rw-r--r-- | src/core/SkPictureRecorder.cpp | 51 |
4 files changed, 83 insertions, 31 deletions
diff --git a/include/core/SkPictureRecorder.h b/include/core/SkPictureRecorder.h index 82efcf0e99..f20a06adf4 100644 --- a/include/core/SkPictureRecorder.h +++ b/include/core/SkPictureRecorder.h @@ -19,6 +19,7 @@ namespace android { }; #endif +class GrContext; class SkCanvas; class SkDrawable; class SkPictureRecord; @@ -111,6 +112,9 @@ public: SkPicture* SK_WARN_UNUSED_RESULT endRecording() { return this->endRecordingAsPicture(); } #endif + // Strawman API. + void optimizeFor(GrContext* ctx) { fGrContextToOptimizeFor = ctx; } + private: void reset(); @@ -131,6 +135,8 @@ private: SkAutoTUnref<SkRecord> fRecord; SkMiniRecorder fMiniRecorder; + GrContext* fGrContextToOptimizeFor = nullptr; + typedef SkNoncopyable INHERITED; }; diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h index 0b50d1163d..32da3dd377 100644 --- a/include/private/SkRecords.h +++ b/include/private/SkRecords.h @@ -153,6 +153,7 @@ enum Tags { kDraw_Tag = 1, // May draw something (usually named DrawFoo). kHasImage_Tag = 2, // Contains an SkImage or SkBitmap. kHasText_Tag = 4, // Contains text. + kHasPaint_Tag = 8, // May have an SkPaint field, at least optionally. }; // A macro to make it a little easier to define a struct that can be stored in SkRecord. @@ -169,7 +170,7 @@ RECORD(Restore, 0, TypedMatrix matrix); RECORD(Save, 0); -RECORD(SaveLayer, 0, +RECORD(SaveLayer, kHasPaint_Tag, Optional<SkRect> bounds; Optional<SkPaint> paint; sk_sp<const SkImageFilter> backdrop; @@ -208,7 +209,7 @@ RECORD(ClipRegion, 0, SkRegion::Op op); // While not strictly required, if you have an SkPaint, it's fastest to put it first. -RECORD(DrawDRRect, kDraw_Tag, +RECORD(DrawDRRect, kDraw_Tag|kHasPaint_Tag, SkPaint paint; SkRRect outer; SkRRect inner); @@ -216,90 +217,90 @@ RECORD(DrawDrawable, kDraw_Tag, Optional<SkMatrix> matrix; SkRect worstCaseBounds; int32_t index); -RECORD(DrawImage, kDraw_Tag|kHasImage_Tag, +RECORD(DrawImage, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, Optional<SkPaint> paint; sk_sp<const SkImage> image; SkScalar left; SkScalar top); -RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag, +RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, Optional<SkPaint> paint; sk_sp<const SkImage> image; Optional<SkRect> src; SkRect dst; SkCanvas::SrcRectConstraint constraint); -RECORD(DrawImageNine, kDraw_Tag|kHasImage_Tag, +RECORD(DrawImageNine, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, Optional<SkPaint> paint; sk_sp<const SkImage> image; SkIRect center; SkRect dst); -RECORD(DrawOval, kDraw_Tag, +RECORD(DrawOval, kDraw_Tag|kHasPaint_Tag, SkPaint paint; SkRect oval); -RECORD(DrawPaint, kDraw_Tag, +RECORD(DrawPaint, kDraw_Tag|kHasPaint_Tag, SkPaint paint); -RECORD(DrawPath, kDraw_Tag, +RECORD(DrawPath, kDraw_Tag|kHasPaint_Tag, SkPaint paint; PreCachedPath path); -RECORD(DrawPicture, kDraw_Tag, +RECORD(DrawPicture, kDraw_Tag|kHasPaint_Tag, Optional<SkPaint> paint; sk_sp<const SkPicture> picture; TypedMatrix matrix); -RECORD(DrawShadowedPicture, kDraw_Tag, +RECORD(DrawShadowedPicture, kDraw_Tag|kHasPaint_Tag, Optional<SkPaint> paint; sk_sp<const SkPicture> picture; TypedMatrix matrix); -RECORD(DrawPoints, kDraw_Tag, +RECORD(DrawPoints, kDraw_Tag|kHasPaint_Tag, SkPaint paint; SkCanvas::PointMode mode; unsigned count; SkPoint* pts); -RECORD(DrawPosText, kDraw_Tag|kHasText_Tag, +RECORD(DrawPosText, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, SkPaint paint; PODArray<char> text; size_t byteLength; PODArray<SkPoint> pos); -RECORD(DrawPosTextH, kDraw_Tag|kHasText_Tag, +RECORD(DrawPosTextH, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, SkPaint paint; PODArray<char> text; unsigned byteLength; SkScalar y; PODArray<SkScalar> xpos); -RECORD(DrawRRect, kDraw_Tag, +RECORD(DrawRRect, kDraw_Tag|kHasPaint_Tag, SkPaint paint; SkRRect rrect); -RECORD(DrawRect, kDraw_Tag, +RECORD(DrawRect, kDraw_Tag|kHasPaint_Tag, SkPaint paint; SkRect rect); -RECORD(DrawText, kDraw_Tag|kHasText_Tag, +RECORD(DrawText, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, SkPaint paint; PODArray<char> text; size_t byteLength; SkScalar x; SkScalar y); -RECORD(DrawTextBlob, kDraw_Tag|kHasText_Tag, +RECORD(DrawTextBlob, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, SkPaint paint; sk_sp<const SkTextBlob> blob; SkScalar x; SkScalar y); -RECORD(DrawTextOnPath, kDraw_Tag|kHasText_Tag, +RECORD(DrawTextOnPath, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, SkPaint paint; PODArray<char> text; size_t byteLength; PreCachedPath path; TypedMatrix matrix); -RECORD(DrawTextRSXform, kDraw_Tag|kHasText_Tag, +RECORD(DrawTextRSXform, kDraw_Tag|kHasText_Tag|kHasPaint_Tag, SkPaint paint; PODArray<char> text; size_t byteLength; PODArray<SkRSXform> xforms; Optional<SkRect> cull); -RECORD(DrawPatch, kDraw_Tag, +RECORD(DrawPatch, kDraw_Tag|kHasPaint_Tag, SkPaint paint; PODArray<SkPoint> cubics; PODArray<SkColor> colors; PODArray<SkPoint> texCoords; sk_sp<SkXfermode> xmode); -RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag, +RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, Optional<SkPaint> paint; sk_sp<const SkImage> atlas; PODArray<SkRSXform> xforms; @@ -308,7 +309,7 @@ RECORD(DrawAtlas, kDraw_Tag|kHasImage_Tag, int count; SkXfermode::Mode mode; Optional<SkRect> cull); -RECORD(DrawVertices, kDraw_Tag, +RECORD(DrawVertices, kDraw_Tag|kHasPaint_Tag, SkPaint paint; SkCanvas::VertexMode vmode; int vertexCount; @@ -318,7 +319,7 @@ RECORD(DrawVertices, kDraw_Tag, sk_sp<SkXfermode> xmode; PODArray<uint16_t> indices; int indexCount); -RECORD(DrawAnnotation, 0, +RECORD(DrawAnnotation, 0, // TODO: kDraw_Tag, skia:5548 SkRect rect; SkString key; sk_sp<SkData> value); diff --git a/src/core/SkPictureCommon.h b/src/core/SkPictureCommon.h index 1c38b049fa..0a0c6b5ca9 100644 --- a/src/core/SkPictureCommon.h +++ b/src/core/SkPictureCommon.h @@ -45,18 +45,12 @@ struct SkBitmapHunter { // Most draws-type ops have paints. template <typename T> - static SK_WHEN(T::kTags & SkRecords::kDraw_Tag, bool) CheckPaint(const T& op) { + static SK_WHEN(T::kTags & SkRecords::kHasPaint_Tag, bool) CheckPaint(const T& op) { return PaintHasBitmap(AsPtr(op.paint)); } - // SaveLayers also have a paint to check. - static bool CheckPaint(const SkRecords::SaveLayer& op) { - return PaintHasBitmap(AsPtr(op.paint)); - } - - // Shouldn't be any non-Draw non-SaveLayer ops with paints. template <typename T> - static SK_WHEN(!(T::kTags & SkRecords::kDraw_Tag), bool) CheckPaint(const T&) { + static SK_WHEN(!(T::kTags & SkRecords::kHasPaint_Tag), bool) CheckPaint(const T&) { return false; } diff --git a/src/core/SkPictureRecorder.cpp b/src/core/SkPictureRecorder.cpp index 5631a081d4..8e7c7f3b06 100644 --- a/src/core/SkPictureRecorder.cpp +++ b/src/core/SkPictureRecorder.cpp @@ -8,6 +8,7 @@ #include "SkBigPicture.h" #include "SkData.h" #include "SkDrawable.h" +#include "SkImage.h" #include "SkPictureRecorder.h" #include "SkPictureUtils.h" #include "SkRecord.h" @@ -16,6 +17,54 @@ #include "SkRecordedDrawable.h" #include "SkRecorder.h" #include "SkTypes.h" +#include "SkTLogic.h" + +namespace SkRecords { + + struct OptimizeFor { + GrContext* fCtx; + + // A few ops have a top-level SkImage: + void operator()(DrawAtlas* op) { this->make_texture(&op->atlas); } + void operator()(DrawImage* op) { this->make_texture(&op->image); } + void operator()(DrawImageNine* op) { this->make_texture(&op->image); } + void operator()(DrawImageRect* op) { this->make_texture(&op->image); } + void make_texture(sk_sp<const SkImage>* img) const { + *img = (*img)->makeTextureImage(fCtx); + } + + // Some ops have a paint, some have an optional paint. + // Either way, get back a pointer. + static SkPaint* AsPtr(SkPaint& p) { return &p; } + static SkPaint* AsPtr(SkRecords::Optional<SkPaint>& p) { return p; } + + // For all other types of ops, look for images inside the paint. + template <typename T> + SK_WHEN(T::kTags & kHasPaint_Tag, void) operator()(T* op) { + SkMatrix matrix; + SkShader::TileMode xy[2]; + + if (auto paint = AsPtr(op->paint)) + if (auto shader = paint->getShader()) + if (auto image = shader->isAImage(&matrix, xy)) { + paint->setShader(image->makeTextureImage(fCtx)->makeShader(xy[0], xy[1], &matrix)); + } + + // TODO: re-build compose shaders + } + + // Control ops, etc. Nothing to do for these. + template <typename T> + SK_WHEN(!(T::kTags & kHasPaint_Tag), void) operator()(T*) {} + }; + +} // namespace SkRecords + +static void optimize_for(GrContext* ctx, SkRecord* record) { + for (int i = 0; ctx && i < record->count(); i++) { + record->mutate(i, SkRecords::OptimizeFor{ctx}); + } +} SkPictureRecorder::SkPictureRecorder() { fActivelyRecording = false; @@ -63,6 +112,7 @@ sk_sp<SkPicture> SkPictureRecorder::finishRecordingAsPicture(uint32_t finishFlag // TODO: delay as much of this work until just before first playback? SkRecordOptimize(fRecord); + optimize_for(fGrContextToOptimizeFor, fRecord); if (fRecord->count() == 0) { if (finishFlags & kReturnNullForEmpty_FinishFlag) { @@ -123,6 +173,7 @@ sk_sp<SkDrawable> SkPictureRecorder::finishRecordingAsDrawable(uint32_t finishFl fRecorder->restoreToCount(1); // If we were missing any restores, add them now. SkRecordOptimize(fRecord); + optimize_for(fGrContextToOptimizeFor, fRecord); if (fRecord->count() == 0) { if (finishFlags & kReturnNullForEmpty_FinishFlag) { |