예제 #1
0
static void TestTLList(skiatest::Reporter* reporter) {
    typedef SkTLList<ListElement> ElList;
    typedef ElList::Iter Iter;
    SkMWCRandom random;

    for (int i = 1; i <= 16; i *= 2) {

        ElList list1(i);
        ElList list2(i);
        Iter iter1;
        Iter iter2;
        Iter iter3;
        Iter iter4;

#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif

        REPORTER_ASSERT(reporter, list1.isEmpty());
        REPORTER_ASSERT(reporter, NULL == iter1.init(list1, Iter::kHead_IterStart));
        REPORTER_ASSERT(reporter, NULL == iter1.init(list1, Iter::kTail_IterStart));
        // Try popping an empty list
        list1.popHead();
        list1.popTail();
        REPORTER_ASSERT(reporter, list1.isEmpty());
        REPORTER_ASSERT(reporter, list1 == list2);

        // Create two identical lists, one by appending to head and the other to the tail.
        list1.addToHead(ListElement(1));
        list2.addToTail(ListElement(1));
#if SK_ENABLE_INST_COUNT
        SkASSERT(2 == ListElement::InstanceCount());
#endif
        iter1.init(list1, Iter::kHead_IterStart);
        iter2.init(list1, Iter::kTail_IterStart);
        REPORTER_ASSERT(reporter, iter1.get()->fID == iter2.get()->fID);
        iter3.init(list2, Iter::kHead_IterStart);
        iter4.init(list2, Iter::kTail_IterStart);
        REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, list1 == list2);

        list2.reset();

        // use both before/after in-place construction on an empty list
        SkNEW_INSERT_IN_LLIST_BEFORE(&list2, list2.headIter(), ListElement, (1));
        REPORTER_ASSERT(reporter, list2 == list1);
        list2.reset();

        SkNEW_INSERT_IN_LLIST_AFTER(&list2, list2.tailIter(), ListElement, (1));
        REPORTER_ASSERT(reporter, list2 == list1);

        // add an element to the second list, check that iters are still valid
        iter3.init(list2, Iter::kHead_IterStart);
        iter4.init(list2, Iter::kTail_IterStart);
        list2.addToHead(ListElement(2));

#if SK_ENABLE_INST_COUNT
        SkASSERT(3 == ListElement::InstanceCount());
#endif

        REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID);
        REPORTER_ASSERT(reporter, 1 == Iter(list2, Iter::kTail_IterStart).get()->fID);
        REPORTER_ASSERT(reporter, 2 == Iter(list2, Iter::kHead_IterStart).get()->fID);
        REPORTER_ASSERT(reporter, list1 != list2);
        list1.addToHead(ListElement(2));
        REPORTER_ASSERT(reporter, list1 == list2);
#if SK_ENABLE_INST_COUNT
        SkASSERT(4 == ListElement::InstanceCount());
#endif
        REPORTER_ASSERT(reporter, !list1.isEmpty());

        list1.reset();
        list2.reset();
#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif
        REPORTER_ASSERT(reporter, list1.isEmpty() && list2.isEmpty());

        // randomly perform insertions and deletions on a list and perform tests
        int count = 0;
        for (int j = 0; j < 100; ++j) {
            if (list1.isEmpty() || random.nextBiasedBool(3  * SK_Scalar1 / 4)) {
                int id = j;
                // Choose one of three ways to insert a new element: at the head, at the tail,
                // before a random element, after a random element
                int numValidMethods = 0 == count ? 2 : 4;
                int insertionMethod = random.nextULessThan(numValidMethods);
                switch (insertionMethod) {
                    case 0:
                        list1.addToHead(ListElement(id));
                        break;
                    case 1:
                        list1.addToTail(ListElement(id));
                        break;
                    case 2: // fallthru to share code that picks random element.
                    case 3: {
                        int n = random.nextULessThan(list1.count());
                        Iter iter = list1.headIter();
                        // remember the elements before/after the insertion point.
                        while (n--) {
                            iter.next();
                        }
                        Iter prev(iter);
                        Iter next(iter);
                        next.next();
                        prev.prev();

                        SkASSERT(NULL != iter.get());
                        // insert either before or after the iterator, then check that the
                        // surrounding sequence is correct.
                        if (2 == insertionMethod) {
                            SkNEW_INSERT_IN_LLIST_BEFORE(&list1, iter, ListElement, (id));
                            Iter newItem(iter);
                            newItem.prev();
                            REPORTER_ASSERT(reporter, newItem.get()->fID == id);

                            if (NULL != next.get()) {
                                REPORTER_ASSERT(reporter, next.prev()->fID == iter.get()->fID);
                            }
                            if (NULL != prev.get()) {
                                REPORTER_ASSERT(reporter, prev.next()->fID == id);
                            }
                        } else {
                            SkNEW_INSERT_IN_LLIST_AFTER(&list1, iter, ListElement, (id));
                            Iter newItem(iter);
                            newItem.next();
                            REPORTER_ASSERT(reporter, newItem.get()->fID == id);

                            if (NULL != next.get()) {
                                REPORTER_ASSERT(reporter, next.prev()->fID == id);
                            }
                            if (NULL != prev.get()) {
                                REPORTER_ASSERT(reporter, prev.next()->fID == iter.get()->fID);
                            }
                        }
                    }
                }
                ++count;
            } else {
                // walk to a random place either forward or backwards and remove.
                int n = random.nextULessThan(list1.count());
                Iter::IterStart start;
                ListElement* (Iter::*incrFunc)();

                if (random.nextBool()) {
                    start = Iter::kHead_IterStart;
                    incrFunc = &Iter::next;
                } else {
                    start = Iter::kTail_IterStart;
                    incrFunc = &Iter::prev;
                }

                // find the element
                Iter iter(list1, start);
                while (n--) {
                    REPORTER_ASSERT(reporter, NULL != iter.get());
                    (iter.*incrFunc)();
                }
                REPORTER_ASSERT(reporter, NULL != iter.get());

                // remember the prev and next elements from the element to be removed
                Iter prev = iter;
                Iter next = iter;
                prev.prev();
                next.next();
                list1.remove(iter.get());

                // make sure the remembered next/prev iters still work
                Iter pn = prev; pn.next();
                Iter np = next; np.prev();
                // pn should match next unless the target node was the head, in which case prev
                // walked off the list.
                REPORTER_ASSERT(reporter, pn.get() == next.get() || NULL == prev.get());
                // Similarly, np should match prev unless next originally walked off the tail.
                REPORTER_ASSERT(reporter, np.get() == prev.get() || NULL == next.get());
                --count;
            }
            REPORTER_ASSERT(reporter, count == list1.count());
#if SK_ENABLE_INST_COUNT
            SkASSERT(count == ListElement::InstanceCount());
#endif
        }
        list1.reset();
#if SK_ENABLE_INST_COUNT
        SkASSERT(0 == ListElement::InstanceCount());
#endif
    }
}
bool GrGpuGL::programUnitTest(int maxStages) {

    GrTextureDesc dummyDesc;
    dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit;
    dummyDesc.fConfig = kSkia8888_GrPixelConfig;
    dummyDesc.fWidth = 34;
    dummyDesc.fHeight = 18;
    SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0));
    dummyDesc.fFlags = kNone_GrTextureFlags;
    dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
    dummyDesc.fWidth = 16;
    dummyDesc.fHeight = 22;
    SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0));

    static const int NUM_TESTS = 512;

    SkMWCRandom random;
    for (int t = 0; t < NUM_TESTS; ++t) {

#if 0
        GrPrintf("\nTest Program %d\n-------------\n", t);
        static const int stop = -1;
        if (t == stop) {
            int breakpointhere = 9;
        }
#endif

        GrGLProgramDesc pdesc;

        int currAttribIndex = 1;  // we need to always leave room for position
        int attribIndices[2];
        GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};

        int numStages = random.nextULessThan(maxStages + 1);
        int numColorStages = random.nextULessThan(numStages + 1);
        int numCoverageStages = numStages - numColorStages;

        SkAutoSTMalloc<8, const GrEffectStage*> stages(numStages);

        for (int s = 0; s < numStages; ++s) {
            SkAutoTUnref<const GrEffectRef> effect(GrEffectTestFactory::CreateStage(
                                                                            &random,
                                                                            this->getContext(),
                                                                            *this->caps(),
                                                                            dummyTextures));
            int numAttribs = (*effect)->numVertexAttribs();

            // If adding this effect would exceed the max attrib count then generate a
            // new random effect.
            if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) {
                --s;
                continue;
            }
            for (int i = 0; i < numAttribs; ++i) {
                attribIndices[i] = currAttribIndex++;
            }
            GrEffectStage* stage = SkNEW_ARGS(GrEffectStage,
                                              (effect.get(), attribIndices[0], attribIndices[1]));
            stages[s] = stage;
        }
        const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
        pdesc.setRandom(&random,
                        this,
                        dummyTextures[0]->asRenderTarget(),
                        dstTexture,
                        stages.get(),
                        numColorStages,
                        numCoverageStages,
                        currAttribIndex);

        SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
                                                              pdesc,
                                                              stages,
                                                              stages + numColorStages));
        for (int s = 0; s < numStages; ++s) {
            SkDELETE(stages[s]);
        }
        if (NULL == program.get()) {
            return false;
        }
    }
    return true;
}