Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Unified Diff: skia/ext/cdl_picture_buffer.cc

Issue 2523673004: [NOT FOR COMMIT] Fully replace SkCanvas uses.
Patch Set: Support Android build. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « skia/ext/cdl_picture_buffer.h ('k') | skia/ext/cdl_picture_recorder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: skia/ext/cdl_picture_buffer.cc
diff --git a/skia/ext/cdl_picture_buffer.cc b/skia/ext/cdl_picture_buffer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cb39a2a442e4aef47230584fb399a71b83bd9bf6
--- /dev/null
+++ b/skia/ext/cdl_picture_buffer.cc
@@ -0,0 +1,698 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "cdl_picture_buffer.h"
+
+#if CDL_ENABLED
+
+#include "base/trace_event/trace_event.h"
+#include "cdl_canvas.h"
+#include "cdl_paint.h"
+#include "cdl_picture.h"
+
+#include "SkCanvas.h"
+#include "SkData.h"
+#include "SkDrawFilter.h"
+#include "SkImageFilter.h"
+#include "SkMath.h"
+#include "SkPicture.h"
+#include "SkRSXform.h"
+#include "SkTextBlob.h"
+
+#ifndef SKLITEDL_PAGE
+#define SKLITEDL_PAGE 4096
+#endif
+
+// A stand-in for an optional SkRect which was not set, e.g. bounds for a
+// saveLayer().
+static const SkRect kUnset = {SK_ScalarInfinity, 0, 0, 0};
+static const SkRect* maybe_unset(const SkRect& r) {
+ return r.left() == SK_ScalarInfinity ? nullptr : &r;
+}
+
+// copy_v(dst, src,n, src,n, ...) copies an arbitrary number of typed srcs into
+// dst.
+static void copy_v(void* dst) {}
+
+template <typename S, typename... Rest>
+static void copy_v(void* dst, const S* src, int n, Rest&&... rest) {
+ SkASSERTF(((uintptr_t)dst & (alignof(S) - 1)) == 0,
+ "Expected %p to be aligned for at least %zu bytes.", dst,
+ alignof(S));
+ sk_careful_memcpy(dst, src, n * sizeof(S));
+ copy_v(SkTAddOffset<void>(dst, n * sizeof(S)), std::forward<Rest>(rest)...);
+}
+
+// Helper for getting back at arrays which have been copy_v'd together after an
+// Op.
+template <typename D, typename T>
+static D* pod(T* op, size_t offset = 0) {
+ return SkTAddOffset<D>(op + 1, offset);
+}
+
+// Pre-cache lazy non-threadsafe fields on SkPath and/or SkMatrix.
+static void make_threadsafe(SkPath* path, SkMatrix* matrix) {
+ if (path) {
+ path->updateBoundsCache();
+ }
+ if (matrix) {
+ (void)matrix->getType();
+ }
+}
+
+namespace {
+#define TYPES(M) \
+ M(SetDrawFilter) \
+ M(Save) \
+ M(Restore) \
+ M(SaveLayer) \
+ M(Concat) \
+ M(SetMatrix) \
+ M(Translate) \
+ M(ClipPath) \
+ M(ClipRect) \
+ M(ClipRRect) \
+ M(ClipRegion) \
+ M(DrawPaint) \
+ M(DrawPath) \
+ M(DrawRect) \
+ M(DrawOval) \
+ M(DrawRRect) \
+ M(DrawDRRect) \
+ M(DrawAnnotation) \
+ M(DrawPicture) \
+ M(DrawImage) \
+ M(DrawImageRect) \
+ M(DrawText) \
+ M(DrawPosText) \
+ M(DrawTextBlob) \
+ M(DrawPoints)
+
+#define M(T) T,
+enum class Type : uint8_t { TYPES(M) };
+#undef M
+
+struct Op {
+ void makeThreadsafe() {}
+
+ uint32_t type : 8;
+ uint32_t skip : 24;
+};
+static_assert(sizeof(Op) == 4, "");
+
+struct SetDrawFilter final : Op {
+#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
+ static const auto kType = Type::SetDrawFilter;
+ SetDrawFilter(SkDrawFilter* df) : drawFilter(sk_ref_sp(df)) {}
+ sk_sp<SkDrawFilter> drawFilter;
+#endif
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
+ c->setDrawFilter(drawFilter.get());
+#endif
+ }
+};
+
+struct Save final : Op {
+ static const auto kType = Type::Save;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->save();
+ }
+};
+struct Restore final : Op {
+ static const auto kType = Type::Restore;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->restore();
+ }
+};
+struct SaveLayer final : Op {
+ static const auto kType = Type::SaveLayer;
+ SaveLayer(const SkRect* bounds,
+ const CdlPaint* paint,
+ const SkImageFilter* backdrop,
+ SkCanvas::SaveLayerFlags flags)
+ : has_paint(false) {
+ if (bounds) {
+ this->bounds = *bounds;
+ }
+ if (paint) {
+ this->paint = *paint;
+ has_paint = true;
+ }
+ this->backdrop = sk_ref_sp(backdrop);
+ this->flags = flags;
+ }
+ SkRect bounds = kUnset;
+ CdlPaint paint;
+ bool has_paint;
+ sk_sp<const SkImageFilter> backdrop;
+ SkCanvas::SaveLayerFlags flags;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->saveLayer({maybe_unset(bounds), has_paint ? &paint : nullptr,
+ backdrop.get(), flags});
+ }
+};
+
+struct Concat final : Op {
+ static const auto kType = Type::Concat;
+ Concat(const SkMatrix& matrix) : matrix(matrix) {}
+ SkMatrix matrix;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->concat(matrix);
+ }
+ void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
+};
+struct SetMatrix final : Op {
+ static const auto kType = Type::SetMatrix;
+ SetMatrix(const SkMatrix& matrix) : matrix(matrix) {}
+ SkMatrix matrix;
+ void draw(CdlCanvas* c,
+ const SkMatrix& original,
+ CdlPictureBuffer::DrawContext&) {
+ c->setMatrix(SkMatrix::Concat(original, matrix));
+ }
+ void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
+};
+struct Translate final : Op {
+ static const auto kType = Type::Translate;
+ Translate(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
+ SkScalar dx, dy;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->translate(dx, dy);
+ }
+};
+
+struct ClipPath final : Op {
+ static const auto kType = Type::ClipPath;
+ ClipPath(const SkPath& path, SkCanvas::ClipOp op, bool aa)
+ : path(path), op(op), aa(aa) {}
+ SkPath path;
+ SkCanvas::ClipOp op;
+ bool aa;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->clipPath(path, op, aa);
+ }
+ void makeThreadsafe() { make_threadsafe(&path, nullptr); }
+};
+struct ClipRect final : Op {
+ static const auto kType = Type::ClipRect;
+ ClipRect(const SkRect& rect, SkCanvas::ClipOp op, bool aa)
+ : rect(rect), op(op), aa(aa) {}
+ SkRect rect;
+ SkCanvas::ClipOp op;
+ bool aa;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->clipRect(rect, op, aa);
+ }
+};
+struct ClipRRect final : Op {
+ static const auto kType = Type::ClipRRect;
+ ClipRRect(const SkRRect& rrect, SkCanvas::ClipOp op, bool aa)
+ : rrect(rrect), op(op), aa(aa) {}
+ SkRRect rrect;
+ SkCanvas::ClipOp op;
+ bool aa;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->clipRRect(rrect, op, aa);
+ }
+};
+struct ClipRegion final : Op {
+ static const auto kType = Type::ClipRegion;
+ ClipRegion(const SkRegion& region, SkCanvas::ClipOp op)
+ : region(region), op(op) {}
+ SkRegion region;
+ SkCanvas::ClipOp op;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->clipRegion(region, op);
+ }
+};
+
+struct DrawPaint final : Op {
+ static const auto kType = Type::DrawPaint;
+ DrawPaint(const CdlPaint& paint) : paint(paint) {}
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawPaint(paint);
+ }
+};
+struct DrawPath final : Op {
+ static const auto kType = Type::DrawPath;
+ DrawPath(const SkPath& path, const CdlPaint& paint)
+ : path(path), paint(paint) {}
+ SkPath path;
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawPath(path, paint);
+ }
+ void makeThreadsafe() { make_threadsafe(&path, nullptr); }
+};
+struct DrawRect final : Op {
+ static const auto kType = Type::DrawRect;
+ DrawRect(const SkRect& rect, const CdlPaint& paint)
+ : rect(rect), paint(paint) {}
+ SkRect rect;
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawRect(rect, paint);
+ }
+};
+
+struct DrawRRect final : Op {
+ static const auto kType = Type::DrawRRect;
+ DrawRRect(const SkRRect& rrect, const CdlPaint& paint)
+ : rrect(rrect), paint(paint) {}
+ SkRRect rrect;
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawRRect(rrect, paint);
+ }
+};
+struct DrawDRRect final : Op {
+ static const auto kType = Type::DrawDRRect;
+ DrawDRRect(const SkRRect& outer, const SkRRect& inner, const CdlPaint& paint)
+ : outer(outer), inner(inner), paint(paint) {}
+ SkRRect outer, inner;
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawDRRect(outer, inner, paint);
+ }
+};
+
+struct DrawOval final : Op {
+ static const auto kType = Type::DrawOval;
+ DrawOval(const SkRect& oval, const CdlPaint& paint)
+ : oval(oval), paint(paint) {}
+ SkRect oval;
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawOval(oval, paint);
+ }
+};
+
+struct DrawAnnotation final : Op {
+ static const auto kType = Type::DrawAnnotation;
+ DrawAnnotation(const SkRect& rect, SkData* value)
+ : rect(rect), value(sk_ref_sp(value)) {}
+ SkRect rect;
+ sk_sp<SkData> value;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ // TODO(cdl)
+ // c->drawAnnotation(rect, pod<char>(this), value.get());
+ }
+};
+
+struct DrawPicture final : Op {
+ static const auto kType = Type::DrawPicture;
+ DrawPicture(const CdlPicture* picture,
+ const SkMatrix* matrix,
+ const CdlPaint* paint)
+ : picture(sk_ref_sp(picture)), has_paint(false) {
+ if (matrix) {
+ this->matrix = *matrix;
+ }
+ if (paint) {
+ this->paint = *paint;
+ has_paint = true;
+ }
+ }
+ sk_sp<const CdlPicture> picture;
+ SkMatrix matrix = SkMatrix::I();
+ CdlPaint paint;
+ bool has_paint; // TODO: why is a default paint not the same?
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr);
+ }
+ void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
+};
+
+struct DrawImage final : Op {
+ static const auto kType = Type::DrawImage;
+ DrawImage(sk_sp<const SkImage>&& image,
+ SkScalar x,
+ SkScalar y,
+ const CdlPaint* paint)
+ : image(std::move(image)), x(x), y(y), has_paint(false) {
+ if (paint) {
+ this->paint = *paint;
+ has_paint = true;
+ }
+ }
+ sk_sp<const SkImage> image;
+ SkScalar x, y;
+ CdlPaint paint;
+ bool has_paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawImage(image.get(), x, y, has_paint ? &paint : nullptr);
+ }
+};
+
+struct DrawImageRect final : Op {
+ static const auto kType = Type::DrawImageRect;
+ DrawImageRect(sk_sp<const SkImage>&& image,
+ const SkRect* src,
+ const SkRect& dst,
+ const CdlPaint* paint,
+ SkCanvas::SrcRectConstraint constraint)
+ : image(std::move(image)),
+ dst(dst),
+ has_paint(false),
+ constraint(constraint) {
+ this->src = src ? *src : SkRect::MakeIWH(image->width(), image->height());
+ if (paint) {
+ this->paint = *paint;
+ has_paint = true;
+ }
+ }
+ sk_sp<const SkImage> image;
+ SkRect src, dst;
+ CdlPaint paint;
+ bool has_paint;
+ SkCanvas::SrcRectConstraint constraint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawImageRect(image.get(), src, dst, has_paint ? &paint : nullptr,
+ constraint);
+ }
+};
+
+struct DrawText final : Op {
+ static const auto kType = Type::DrawText;
+ DrawText(size_t bytes, SkScalar x, SkScalar y, const CdlPaint& paint)
+ : bytes(bytes), x(x), y(y), paint(paint) {}
+ size_t bytes;
+ SkScalar x, y;
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawText(pod<void>(this), bytes, x, y, paint);
+ }
+};
+struct DrawPosText final : Op {
+ static const auto kType = Type::DrawPosText;
+ DrawPosText(size_t bytes, const CdlPaint& paint, int n)
+ : bytes(bytes), paint(paint), n(n) {}
+ size_t bytes;
+ CdlPaint paint;
+ int n;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ auto points = pod<SkPoint>(this);
+ auto text = pod<void>(this, n * sizeof(SkPoint));
+ c->drawPosText(text, bytes, points, paint);
+ }
+};
+
+struct DrawTextBlob final : Op {
+ static const auto kType = Type::DrawTextBlob;
+ DrawTextBlob(const SkTextBlob* blob,
+ SkScalar x,
+ SkScalar y,
+ const CdlPaint& paint)
+ : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {}
+ sk_sp<const SkTextBlob> blob;
+ SkScalar x, y;
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext& dc) {
+ c->drawTextBlob(blob.get(), x, y, paint);
+ }
+};
+
+struct DrawPoints final : Op {
+ static const auto kType = Type::DrawPoints;
+ DrawPoints(SkCanvas::PointMode mode, size_t count, const CdlPaint& paint)
+ : mode(mode), count(count), paint(paint) {}
+ SkCanvas::PointMode mode;
+ size_t count;
+ CdlPaint paint;
+ void draw(CdlCanvas* c, const SkMatrix&, CdlPictureBuffer::DrawContext&) {
+ c->drawPoints(mode, count, pod<SkPoint>(this), paint);
+ }
+};
+
+} // anon namespace
+
+template <typename T, typename... Args>
+void* CdlPictureBuffer::push(size_t pod, Args&&... args) {
+ size_t skip = SkAlignPtr(sizeof(T) + pod);
+ SkASSERT(skip < (1 << 24));
+ if (fUsed + skip > fReserved) {
+ static_assert(SkIsPow2(SKLITEDL_PAGE),
+ "This math needs updating for non-pow2.");
+ // Next greater multiple of SKLITEDL_PAGE.
+ fReserved = (fUsed + skip + SKLITEDL_PAGE) & ~(SKLITEDL_PAGE - 1);
+ fBytes.realloc(fReserved);
+ }
+ SkASSERT(fUsed + skip <= fReserved);
+ auto op = (T*)(fBytes.get() + fUsed);
+ fUsed += skip;
+ new (op) T{std::forward<Args>(args)...};
+ op->type = (uint32_t)T::kType;
+ op->skip = skip;
+ return op + 1;
+}
+
+template <typename Fn, typename... Args>
+inline void CdlPictureBuffer::map(const Fn fns[],
+ int start_offset,
+ int end_offset,
+ Args... args) {
+ auto start = fBytes.get() + start_offset;
+ auto end = fBytes.get() + end_offset;
+ for (uint8_t* ptr = start; ptr < end;) {
+ auto op = (Op*)ptr;
+ auto type = op->type;
+ auto skip = op->skip;
+ if (auto fn = fns[type]) { // We replace no-op functions with nullptrs
+ fn(op, args...); // to avoid the overhead of a pointless call.
+ }
+ ptr += skip;
+ }
+}
+
+#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
+void CdlPictureBuffer::setDrawFilter(SkDrawFilter* df) {
+ this->push<SetDrawFilter>(0, df);
+}
+#endif
+
+void CdlPictureBuffer::save() {
+ this->push<Save>(0);
+}
+void CdlPictureBuffer::restore() {
+ this->push<Restore>(0);
+}
+void CdlPictureBuffer::saveLayer(const SkRect* bounds,
+ const CdlPaint* paint,
+ const SkImageFilter* backdrop,
+ SkCanvas::SaveLayerFlags flags) {
+ this->push<SaveLayer>(0, bounds, paint, backdrop, flags);
+}
+
+void CdlPictureBuffer::concat(const SkMatrix& matrix) {
+ this->push<Concat>(0, matrix);
+}
+void CdlPictureBuffer::setMatrix(const SkMatrix& matrix) {
+ this->push<SetMatrix>(0, matrix);
+}
+void CdlPictureBuffer::translate(SkScalar dx, SkScalar dy) {
+ this->push<Translate>(0, dx, dy);
+}
+
+void CdlPictureBuffer::clipPath(const SkPath& path,
+ SkCanvas::ClipOp op,
+ bool aa) {
+ this->push<ClipPath>(0, path, op, aa);
+}
+void CdlPictureBuffer::clipRect(const SkRect& rect,
+ SkCanvas::ClipOp op,
+ bool aa) {
+ this->push<ClipRect>(0, rect, op, aa);
+}
+void CdlPictureBuffer::clipRRect(const SkRRect& rrect,
+ SkCanvas::ClipOp op,
+ bool aa) {
+ this->push<ClipRRect>(0, rrect, op, aa);
+}
+void CdlPictureBuffer::clipRegion(const SkRegion& region, SkCanvas::ClipOp op) {
+ this->push<ClipRegion>(0, region, op);
+}
+
+void CdlPictureBuffer::drawPaint(const CdlPaint& paint) {
+ this->push<DrawPaint>(0, paint);
+}
+void CdlPictureBuffer::drawPath(const SkPath& path, const CdlPaint& paint) {
+ this->push<DrawPath>(0, path, paint);
+}
+void CdlPictureBuffer::drawRect(const SkRect& rect, const CdlPaint& paint) {
+ this->push<DrawRect>(0, rect, paint);
+}
+
+void CdlPictureBuffer::drawRRect(const SkRRect& rrect, const CdlPaint& paint) {
+ this->push<DrawRRect>(0, rrect, paint);
+}
+void CdlPictureBuffer::drawDRRect(const SkRRect& outer,
+ const SkRRect& inner,
+ const CdlPaint& paint) {
+ this->push<DrawDRRect>(0, outer, inner, paint);
+}
+
+void CdlPictureBuffer::drawOval(const SkRect& oval, const CdlPaint& paint) {
+ this->push<DrawOval>(0, oval, paint);
+}
+
+void CdlPictureBuffer::drawAnnotation(const SkRect& rect,
+ const char* key,
+ SkData* value) {
+ size_t bytes = strlen(key) + 1;
+ void* pod = this->push<DrawAnnotation>(bytes, rect, value);
+ copy_v(pod, key, bytes);
+}
+
+void CdlPictureBuffer::drawPicture(const CdlPicture* picture,
+ const SkMatrix* matrix,
+ const CdlPaint* paint) {
+ this->push<DrawPicture>(0, picture, matrix, paint);
+}
+
+void CdlPictureBuffer::drawImage(sk_sp<const SkImage> image,
+ SkScalar x,
+ SkScalar y,
+ const CdlPaint* paint) {
+ this->push<DrawImage>(0, std::move(image), x, y, paint);
+}
+
+void CdlPictureBuffer::drawImageRect(sk_sp<const SkImage> image,
+ const SkRect* src,
+ const SkRect& dst,
+ const CdlPaint* paint,
+ SkCanvas::SrcRectConstraint constraint) {
+ this->push<DrawImageRect>(0, std::move(image), src, dst, paint, constraint);
+}
+
+void CdlPictureBuffer::drawText(const void* text,
+ size_t bytes,
+ SkScalar x,
+ SkScalar y,
+ const CdlPaint& paint) {
+ void* pod = this->push<DrawText>(bytes, bytes, x, y, paint);
+ copy_v(pod, (const char*)text, bytes);
+}
+void CdlPictureBuffer::drawPosText(const void* text,
+ size_t bytes,
+ const SkPoint pos[],
+ const CdlPaint& paint) {
+ int n = paint.toSkPaint().countText(text, bytes);
+ void* pod =
+ this->push<DrawPosText>(n * sizeof(SkPoint) + bytes, bytes, paint, n);
+ copy_v(pod, pos, n, (const char*)text, bytes);
+}
+
+void CdlPictureBuffer::drawTextBlob(const SkTextBlob* blob,
+ SkScalar x,
+ SkScalar y,
+ const CdlPaint& paint) {
+ this->push<DrawTextBlob>(0, blob, x, y, paint);
+}
+
+void CdlPictureBuffer::drawPoints(SkCanvas::PointMode mode,
+ size_t count,
+ const SkPoint points[],
+ const CdlPaint& paint) {
+ void* pod =
+ this->push<DrawPoints>(count * sizeof(SkPoint), mode, count, paint);
+ copy_v(pod, points, count);
+}
+
+typedef void (*draw_fn)(void*,
+ CdlCanvas*,
+ const SkMatrix&,
+ CdlPictureBuffer::DrawContext&);
+typedef void (*void_fn)(void*);
+
+// All ops implement draw().
+#define M(T) \
+ [](void* op, CdlCanvas* c, const SkMatrix& original, \
+ CdlPictureBuffer::DrawContext& dc) { ((T*)op)->draw(c, original, dc); },
+static const draw_fn draw_fns[] = {TYPES(M)};
+#undef M
+
+#define M(T) [](void* op) { ((T*)op)->makeThreadsafe(); },
+static const void_fn make_threadsafe_fns[] = {TYPES(M)};
+#undef M
+
+// Older libstdc++ has pre-standard std::has_trivial_destructor.
+#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20130000)
+template <typename T>
+using can_skip_destructor = std::has_trivial_destructor<T>;
+#else
+template <typename T>
+using can_skip_destructor = std::is_trivially_destructible<T>;
+#endif
+
+// Most state ops (matrix, clip, save, restore) have a trivial destructor.
+#define M(T) \
+ !can_skip_destructor<T>::value ? [](void* op) { ((T*)op)->~T(); } \
+ : (void_fn) nullptr,
+static const void_fn dtor_fns[] = {TYPES(M)};
+#undef M
+
+void CdlPictureBuffer::playback(CdlCanvas* canvas,
+ int start_offset,
+ int end_offset) {
+ DrawContext dc;
+ this->map(draw_fns, start_offset, end_offset, canvas,
+ canvas->getTotalMatrix(), dc);
+}
+
+void CdlPictureBuffer::makeThreadsafe() {
+ this->map(make_threadsafe_fns, 0, fUsed);
+}
+
+SkRect CdlPictureBuffer::getBounds() {
+ return fBounds;
+}
+
+CdlPictureBuffer::CdlPictureBuffer(SkRect bounds)
+ : fUsed(0), fReserved(0), fBounds(bounds) {}
+
+CdlPictureBuffer::~CdlPictureBuffer() {
+ this->reset(SkRect::MakeEmpty());
+}
+
+void CdlPictureBuffer::resetForNextPicture(SkRect bounds) {
+ fBounds = bounds;
+}
+
+void CdlPictureBuffer::reset(SkRect bounds) {
+ SkASSERT(this->unique());
+ this->map(dtor_fns, 0, fUsed);
+
+ // Leave fBytes and fReserved alone.
+ fUsed = 0;
+ fBounds = bounds;
+}
+
+void CdlPictureBuffer::drawAsLayer(CdlCanvas* canvas,
+ const SkMatrix* matrix,
+ const SkPaint* paint) {
+ // TODO(cdl)
+ /*
+ auto fallback_plan = [&] {
+ SkRect bounds = this->getBounds();
+ canvas->saveLayer(&bounds, paint);
+ this->draw(canvas, matrix);
+ canvas->restore();
+ };
+
+ // TODO: single-draw specializations
+
+ return fallback_plan();
+ */
+}
+
+void CdlPictureBuffer::setBounds(const SkRect& bounds) {
+ fBounds = bounds;
+}
+
+#endif // CDL_ENABLED
« no previous file with comments | « skia/ext/cdl_picture_buffer.h ('k') | skia/ext/cdl_picture_recorder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698