From 360b6801cfd90485891d709e44cf395d527ba69e Mon Sep 17 00:00:00 2001 From: cdalton Date: Tue, 14 Oct 2014 11:53:04 -0700 Subject: 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 --- tests/GrTRecorderTest.cpp | 245 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 tests/GrTRecorderTest.cpp (limited to 'tests/GrTRecorderTest.cpp') 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 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 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(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 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(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(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(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(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 -- cgit v1.2.3