aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/GrTRecorderTest.cpp
diff options
context:
space:
mode:
authorGravatar cdalton <cdalton@nvidia.com>2014-10-14 11:53:04 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-14 11:53:05 -0700
commit360b6801cfd90485891d709e44cf395d527ba69e (patch)
tree87751f5acbe9485464cced198d104a3a3cce9590 /tests/GrTRecorderTest.cpp
parente30597375c19dfb5197fd065a3d1768401eb00fa (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(). 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