aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/GrTRecorderTest.cpp
diff options
context:
space:
mode:
authorGravatar cdalton <cdalton@nvidia.com>2014-10-15 13:43:48 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-15 13:43:48 -0700
commit6819df36446f6fdcbd17d83a72a03de46e6d0d2d (patch)
tree4edbd494f61991b0165806f994137a4bf77b96fe /tests/GrTRecorderTest.cpp
parent80a720eb823ac76fdfa254fe9b9f7333a1458e5c (diff)
Adds a GrTRecorder class that GrInOrderDrawBuffer uses to allocate
all its commands interleaved in contiguous memory. GrTRecorder also supports extra data associated with objects, so we can store arrays inline without having to call malloc(). Committed: https://skia.googlesource.com/skia/+/360b6801cfd90485891d709e44cf395d527ba69e Review URL: https://codereview.chromium.org/628453002
Diffstat (limited to 'tests/GrTRecorderTest.cpp')
-rw-r--r--tests/GrTRecorderTest.cpp245
1 files changed, 245 insertions, 0 deletions
diff --git a/tests/GrTRecorderTest.cpp b/tests/GrTRecorderTest.cpp
new file mode 100644
index 0000000000..a5aedf687c
--- /dev/null
+++ b/tests/GrTRecorderTest.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#if SK_SUPPORT_GPU
+
+#include "SkMatrix.h"
+#include "SkString.h"
+#include "GrTRecorder.h"
+#include "Test.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+static int activeRecorderItems = 0;
+
+class IntWrapper {
+public:
+ IntWrapper() {}
+ IntWrapper(int value) : fValue(value) {}
+ operator int() { return fValue; }
+private:
+ int fValue;
+};
+
+static void test_empty_back(skiatest::Reporter* reporter) {
+ GrTRecorder<IntWrapper, int> recorder(0);
+
+ REPORTER_ASSERT(reporter, recorder.empty());
+
+ for (int i = 0; i < 100; ++i) {
+ REPORTER_ASSERT(reporter, i == *GrNEW_APPEND_TO_RECORDER(recorder, IntWrapper, (i)));
+ REPORTER_ASSERT(reporter, !recorder.empty());
+ REPORTER_ASSERT(reporter, i == recorder.back());
+ }
+
+ REPORTER_ASSERT(reporter, !recorder.empty());
+
+ recorder.reset();
+
+ REPORTER_ASSERT(reporter, recorder.empty());
+}
+
+struct ExtraData {
+ typedef GrTRecorder<ExtraData, int> Recorder;
+
+ ExtraData(int i) : fData(i) {
+ int* extraData = this->extraData();
+ for (int j = 0; j < i; j++) {
+ extraData[j] = i;
+ }
+ ++activeRecorderItems;
+ }
+ ~ExtraData() {
+ --activeRecorderItems;
+ }
+ int* extraData() {
+ return reinterpret_cast<int*>(Recorder::GetDataForItem(this));
+ }
+ int fData;
+};
+
+static void test_extra_data(skiatest::Reporter* reporter) {
+ ExtraData::Recorder recorder(0);
+ for (int i = 0; i < 100; ++i) {
+ GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, ExtraData, (i), i * sizeof(int));
+ }
+ REPORTER_ASSERT(reporter, 100 == activeRecorderItems);
+
+ ExtraData::Recorder::Iter iter(recorder);
+ for (int i = 0; i < 100; ++i) {
+ REPORTER_ASSERT(reporter, iter.next());
+ REPORTER_ASSERT(reporter, i == iter->fData);
+ for (int j = 0; j < i; j++) {
+ REPORTER_ASSERT(reporter, i == iter->extraData()[j]);
+ }
+ }
+ REPORTER_ASSERT(reporter, !iter.next());
+
+ recorder.reset();
+ REPORTER_ASSERT(reporter, 0 == activeRecorderItems);
+}
+
+enum ClassType {
+ kBase_ClassType,
+ kSubclass_ClassType,
+ kSubSubclass_ClassType,
+ kSubclassExtraData_ClassType,
+ kSubclassEmpty_ClassType,
+
+ kNumClassTypes
+};
+
+class Base {
+public:
+ typedef GrTRecorder<Base, void*> Recorder;
+
+ Base() {
+ fMatrix.reset();
+ ++activeRecorderItems;
+ }
+
+ virtual ~Base() { --activeRecorderItems; }
+
+ virtual ClassType getType() { return kBase_ClassType; }
+
+ virtual void validate(skiatest::Reporter* reporter) const {
+ REPORTER_ASSERT(reporter, fMatrix.isIdentity());
+ }
+
+private:
+ SkMatrix fMatrix;
+};
+
+class Subclass : public Base {
+public:
+ Subclass() : fString("Lorem ipsum dolor sit amet") {}
+
+ virtual ClassType getType() { return kSubclass_ClassType; }
+
+ virtual void validate(skiatest::Reporter* reporter) const {
+ Base::validate(reporter);
+ REPORTER_ASSERT(reporter, !strcmp("Lorem ipsum dolor sit amet", fString.c_str()));
+ }
+
+private:
+ SkString fString;
+};
+
+class SubSubclass : public Subclass {
+public:
+ SubSubclass() : fInt(1234), fFloat(1.234f) {}
+
+ virtual ClassType getType() { return kSubSubclass_ClassType; }
+
+ virtual void validate(skiatest::Reporter* reporter) const {
+ Subclass::validate(reporter);
+ REPORTER_ASSERT(reporter, 1234 == fInt);
+ REPORTER_ASSERT(reporter, 1.234f == fFloat);
+ }
+
+private:
+ int fInt;
+ float fFloat;
+};
+
+class SubclassExtraData : public Base {
+public:
+ SubclassExtraData(int length) : fLength(length) {
+ int* data = reinterpret_cast<int*>(Recorder::GetDataForItem(this));
+ for (int i = 0; i < fLength; ++i) {
+ data[i] = ValueAt(i);
+ }
+ }
+
+ virtual ClassType getType() { return kSubclassExtraData_ClassType; }
+
+ virtual void validate(skiatest::Reporter* reporter) const {
+ Base::validate(reporter);
+ const int* data = reinterpret_cast<const int*>(Recorder::GetDataForItem(this));
+ for (int i = 0; i < fLength; ++i) {
+ REPORTER_ASSERT(reporter, ValueAt(i) == data[i]);
+ }
+ }
+
+private:
+ static int ValueAt(uint64_t i) { return static_cast<int>(123456789 + 987654321 * i); }
+ int fLength;
+};
+
+class SubclassEmpty : public Base {
+public:
+ virtual ClassType getType() { return kSubclassEmpty_ClassType; }
+};
+
+static void test_subclasses(skiatest::Reporter* reporter) {
+ class Order {
+ public:
+ Order() { this->reset(); }
+ void reset() { fCurrent = 0; }
+ ClassType next() {
+ fCurrent = 1664525 * fCurrent + 1013904223;
+ return static_cast<ClassType>(fCurrent % kNumClassTypes);
+ }
+ private:
+ uint32_t fCurrent;
+ };
+
+ Base::Recorder recorder(1024);
+
+ Order order;
+ for (int i = 0; i < 1000; i++) {
+ switch (order.next()) {
+ case kBase_ClassType:
+ GrNEW_APPEND_TO_RECORDER(recorder, Base, ());
+ break;
+
+ case kSubclass_ClassType:
+ GrNEW_APPEND_TO_RECORDER(recorder, Subclass, ());
+ break;
+
+ case kSubSubclass_ClassType:
+ GrNEW_APPEND_TO_RECORDER(recorder, SubSubclass, ());
+ break;
+
+ case kSubclassExtraData_ClassType:
+ GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassExtraData, (i), sizeof(int) * i);
+ break;
+
+ case kSubclassEmpty_ClassType:
+ GrNEW_APPEND_TO_RECORDER(recorder, SubclassEmpty, ());
+ break;
+
+ default:
+ reporter->reportFailed(SkString("Invalid class type"));
+ break;
+ }
+ }
+ REPORTER_ASSERT(reporter, 1000 == activeRecorderItems);
+
+ order.reset();
+ Base::Recorder::Iter iter(recorder);
+ for (int i = 0; i < 1000; ++i) {
+ REPORTER_ASSERT(reporter, iter.next());
+ REPORTER_ASSERT(reporter, order.next() == iter->getType());
+ iter->validate(reporter);
+ }
+ REPORTER_ASSERT(reporter, !iter.next());
+
+ // Don't reset the recorder. It should automatically destruct all its items.
+}
+
+DEF_GPUTEST(GrTRecorder, reporter, factory) {
+ test_empty_back(reporter);
+
+ test_extra_data(reporter);
+ REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // test_extra_data should call reset().
+
+ test_subclasses(reporter);
+ REPORTER_ASSERT(reporter, 0 == activeRecorderItems); // Ensure ~GrTRecorder invokes dtors.
+}
+
+#endif