Index: tests/MatrixClipCollapseTest.cpp |
=================================================================== |
--- tests/MatrixClipCollapseTest.cpp (revision 0) |
+++ tests/MatrixClipCollapseTest.cpp (revision 0) |
@@ -0,0 +1,716 @@ |
+/* |
+ * Copyright 2014 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "Test.h" |
+#include "SkCanvas.h" |
+#include "SkDebugCanvas.h" |
+#include "SkPicture.h" |
+#include "SkPictureFlat.h" |
+#include "SkPictureRecord.h" |
+ |
+// This test exercises the Matrix/Clip State collapsing system. It generates |
+// example skps and the compares the actual stored operations to the expected |
+// operations. The test works by emitting canvas operations at three levels: |
+// overall structure, bodies that draw something and model/clip state changes. |
+// |
+// Structure methods only directly emit save and restores but call the |
+// ModelClip and Body helper methods to fill in the structure. Since they only |
+// emit saves and restores the operations emitted by the structure methods will |
+// be completely removed by the matrix/clip collapse. Note: every save in |
+// a structure method is followed by a call to a ModelClip helper. |
+// |
+// Body methods only directly emit draw ops and saveLayer/restore pairs but call |
+// the ModelClip helper methods. Since the body methods emit the ops that cannot |
+// be collapsed (i.e., draw ops, saveLayer/restore) they also generate the |
+// expected result information. Note: every saveLayer in a body method is |
+// followed by a call to a ModelClip helper. |
+// |
+// The ModelClip methods output matrix and clip ops in various orders and |
+// combinations. They contribute to the expected result by outputting the |
+// expected matrix & clip ops. Note that, currently, the entire clip stack |
+// is output for each MC state so the clip operations accumulate down the |
+// save/restore stack. |
+ |
+// TODOs: |
+// check on clip offsets |
+// - not sure if this is possible. The desire is to verify that the clip |
+// operations' offsets point to the correct follow-on operations. This |
+// could be difficult since there is no good way to communicate the |
+// offset stored in the SkPicture to the debugger's clip objects |
+// add comparison of rendered before & after images? |
+// - not sure if this would be useful since it somewhat duplicates the |
+// correctness test of running render_pictures in record mode and |
+// rendering before and after images. Additionally the matrix/clip collapse |
+// is sure to cause some small differences so an automated test might |
+// yield too many false positives. |
+// run the matrix/clip collapse system on the 10K skp set |
+// - this should give us warm fuzzies that the matrix clip collapse |
+// system is ready for prime time |
+// bench the recording times with/without matrix/clip collapsing |
+ |
+#ifdef COLLAPSE_MATRIX_CLIP_STATE |
+ |
+// Extract the command ops from the input SkPicture |
+static void gets_ops(SkPicture& input, SkTDArray<DrawType>* ops) { |
+ SkDebugCanvas debugCanvas(input.width(), input.height()); |
+ debugCanvas.setBounds(input.width(), input.height()); |
+ input.draw(&debugCanvas); |
+ |
+ ops->setCount(debugCanvas.getSize()); |
+ for (int i = 0; i < debugCanvas.getSize(); ++i) { |
+ (*ops)[i] = debugCanvas.getDrawCommandAt(i)->getType(); |
+ } |
+} |
+ |
+enum ClipType { |
+ kNone_ClipType, |
+ kRect_ClipType, |
+ kRRect_ClipType, |
+ kPath_ClipType, |
+ kRegion_ClipType, |
+ |
+ kLast_ClipType = kRRect_ClipType |
+}; |
+ |
+static const int kClipTypeCount = kLast_ClipType + 1; |
+ |
+enum MatType { |
+ kNone_MatType, |
+ kTranslate_MatType, |
+ kScale_MatType, |
+ kSkew_MatType, |
+ kRotate_MatType, |
+ kConcat_MatType, |
+ kSetMatrix_MatType, |
+ |
+ kLast_MatType = kScale_MatType |
+}; |
+ |
+static const int kMatTypeCount = kLast_MatType + 1; |
+ |
+// TODO: implement the rest of the draw ops |
+enum DrawOpType { |
+ kNone_DrawOpType, |
+#if 0 |
+ kBitmap_DrawOpType, |
+ kBitmapMatrix_DrawOpType, |
+ kBitmapNone_DrawOpType, |
+ kBitmapRectToRect_DrawOpType, |
+#endif |
+ kClear_DrawOpType, |
+#if 0 |
+ kData_DrawOpType, |
+#endif |
+ kOval_DrawOpType, |
+#if 0 |
+ kPaint_DrawOpType, |
+ kPath_DrawOpType, |
+ kPicture_DrawOpType, |
+ kPoints_DrawOpType, |
+ kPosText_DrawOpType, |
+ kPosTextTopBottom_DrawOpType, |
+ kPosTextH_DrawOpType, |
+ kPosTextHTopBottom_DrawOpType, |
+#endif |
+ kRect_DrawOpType, |
+ kRRect_DrawOpType, |
+#if 0 |
+ kSprite_DrawOpType, |
+ kText_DrawOpType, |
+ kTextOnPath_DrawOpType, |
+ kTextTopBottom_DrawOpType, |
+ kDrawVertices_DrawOpType, |
+#endif |
+ |
+ kLast_DrawOpType = kRect_DrawOpType |
+}; |
+ |
+static const int kDrawOpTypeCount = kLast_DrawOpType + 1; |
+ |
+typedef void (*PFEmitMC)(SkCanvas* canvas, MatType mat, ClipType clip, |
+ DrawOpType draw, SkTDArray<DrawType>* expected, |
+ int accumulatedClips); |
+typedef void (*PFEmitBody)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, |
+ ClipType clip, DrawOpType draw, |
+ SkTDArray<DrawType>* expected, int accumulatedClips); |
+typedef void (*PFEmitStruct)(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, |
+ ClipType clip, PFEmitBody emitBody, DrawOpType draw, |
+ SkTDArray<DrawType>* expected); |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+// TODO: expand the testing to include the different ops & AA types! |
+static void emit_clip(SkCanvas* canvas, ClipType clip) { |
+ switch (clip) { |
+ case kNone_ClipType: |
+ break; |
+ case kRect_ClipType: { |
+ SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); |
+ canvas->clipRect(r, SkRegion::kIntersect_Op, true); |
+ break; |
+ } |
+ case kRRect_ClipType: { |
+ SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); |
+ SkRRect rr; |
+ rr.setRectXY(r, 10, 10); |
+ canvas->clipRRect(rr, SkRegion::kIntersect_Op, true); |
+ break; |
+ } |
+ case kPath_ClipType: { |
+ SkPath p; |
+ p.moveTo(5.0f, 5.0f); |
+ p.lineTo(50.0f, 50.0f); |
+ p.lineTo(100.0f, 5.0f); |
+ p.close(); |
+ canvas->clipPath(p, SkRegion::kIntersect_Op, true); |
+ break; |
+ } |
+ case kRegion_ClipType: { |
+ SkIRect rects[2] = { |
+ { 1, 1, 55, 55 }, |
+ { 45, 45, 99, 99 }, |
+ }; |
+ SkRegion r; |
+ r.setRects(rects, 2); |
+ canvas->clipRegion(r, SkRegion::kIntersect_Op); |
+ break; |
+ } |
+ default: |
+ SkASSERT(0); |
+ } |
+} |
+ |
+static void add_clip(ClipType clip, MatType mat, SkTDArray<DrawType>* expected) { |
+ if (NULL == expected) { |
+ // expected is NULL if this clip will be fused into later clips |
+ return; |
+ } |
+ |
+ switch (clip) { |
+ case kNone_ClipType: |
+ break; |
+ case kRect_ClipType: |
+ *expected->append() = CONCAT; |
+ *expected->append() = CLIP_RECT; |
+ break; |
+ case kRRect_ClipType: |
+ *expected->append() = CONCAT; |
+ *expected->append() = CLIP_RRECT; |
+ break; |
+ case kPath_ClipType: |
+ *expected->append() = CONCAT; |
+ *expected->append() = CLIP_PATH; |
+ break; |
+ case kRegion_ClipType: |
+ *expected->append() = CONCAT; |
+ *expected->append() = CLIP_REGION; |
+ break; |
+ default: |
+ SkASSERT(0); |
+ } |
+} |
+ |
+static void emit_mat(SkCanvas* canvas, MatType mat) { |
+ switch (mat) { |
+ case kNone_MatType: |
+ break; |
+ case kTranslate_MatType: |
+ canvas->translate(5.0f, 5.0f); |
+ break; |
+ case kScale_MatType: |
+ canvas->scale(1.1f, 1.1f); |
+ break; |
+ case kSkew_MatType: |
+ canvas->skew(1.1f, 1.1f); |
+ break; |
+ case kRotate_MatType: |
+ canvas->rotate(1.0f); |
+ break; |
+ case kConcat_MatType: { |
+ SkMatrix m; |
+ m.setTranslate(1.0f, 1.0f); |
+ canvas->concat(m); |
+ break; |
+ } |
+ case kSetMatrix_MatType: { |
+ SkMatrix m; |
+ m.setTranslate(1.0f, 1.0f); |
+ canvas->setMatrix(m); |
+ break; |
+ } |
+ default: |
+ SkASSERT(0); |
+ } |
+} |
+ |
+static void add_mat(MatType mat, SkTDArray<DrawType>* expected) { |
+ if (NULL == expected) { |
+ // expected is NULL if this matrix call will be fused into later ones |
+ return; |
+ } |
+ |
+ switch (mat) { |
+ case kNone_MatType: |
+ break; |
+ case kTranslate_MatType: // fall thru |
+ case kScale_MatType: // fall thru |
+ case kSkew_MatType: // fall thru |
+ case kRotate_MatType: // fall thru |
+ case kConcat_MatType: // fall thru |
+ case kSetMatrix_MatType: |
+ // TODO: this system currently converts a setMatrix to concat. If we wanted to |
+ // really preserve the setMatrix semantics we should keep it a setMatrix. I'm |
+ // not sure if this is a good idea though since this would keep things like pinch |
+ // zoom from working. |
+ *expected->append() = CONCAT; |
+ break; |
+ default: |
+ SkASSERT(0); |
+ } |
+} |
+ |
+static void emit_draw(SkCanvas* canvas, DrawOpType draw, SkTDArray<DrawType>* expected) { |
+ switch (draw) { |
+ case kNone_DrawOpType: |
+ break; |
+ case kClear_DrawOpType: |
+ canvas->clear(SK_ColorRED); |
+ *expected->append() = DRAW_CLEAR; |
+ break; |
+ case kOval_DrawOpType: { |
+ SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); |
+ SkPaint p; |
+ canvas->drawOval(r, p); |
+ *expected->append() = DRAW_OVAL; |
+ break; |
+ } |
+ case kRect_DrawOpType: { |
+ SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); |
+ SkPaint p; |
+ canvas->drawRect(r, p); |
+ *expected->append() = DRAW_RECT; |
+ break; |
+ } |
+ case kRRect_DrawOpType: { |
+ SkRect r = SkRect::MakeLTRB(10.0f, 10.0f, 90.0f, 90.0f); |
+ SkRRect rr; |
+ rr.setRectXY(r, 5.0f, 5.0f); |
+ SkPaint p; |
+ canvas->drawRRect(rr, p); |
+ *expected->append() = DRAW_RRECT; |
+ break; |
+ } |
+ default: |
+ SkASSERT(0); |
+ } |
+} |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+// Emit: |
+// clip |
+// matrix |
+// Simple case - the clip isn't effect by the matrix |
+static void emit_clip_and_mat(SkCanvas* canvas, MatType mat, ClipType clip, |
+ DrawOpType draw, SkTDArray<DrawType>* expected, |
+ int accumulatedClips) { |
+ if (kNone_DrawOpType == draw) { |
+ return; |
+ } |
+ |
+ emit_clip(canvas, clip); |
+ emit_mat(canvas, mat); |
+ |
+ for (int i = 0; i < accumulatedClips; ++i) { |
+ add_clip(clip, mat, expected); |
+ } |
+ add_mat(mat, expected); |
+} |
+ |
+// Emit: |
+// matrix |
+// clip |
+// Emitting the matrix first is more challenging since the matrix has to be |
+// pushed across (i.e., applied to) the clip. |
+static void emit_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip, |
+ DrawOpType draw, SkTDArray<DrawType>* expected, |
+ int accumulatedClips) { |
+ if (kNone_DrawOpType == draw) { |
+ return; |
+ } |
+ |
+ emit_mat(canvas, mat); |
+ emit_clip(canvas, clip); |
+ |
+ // the matrix & clip order will be reversed once collapsed! |
+ for (int i = 0; i < accumulatedClips; ++i) { |
+ add_clip(clip, mat, expected); |
+ } |
+ add_mat(mat, expected); |
+} |
+ |
+// Emit: |
+// matrix |
+// clip |
+// matrix |
+// clip |
+// This tests that the matrices and clips coalesce when collapsed |
+static void emit_double_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip, |
+ DrawOpType draw, SkTDArray<DrawType>* expected, |
+ int accumulatedClips) { |
+ if (kNone_DrawOpType == draw) { |
+ return; |
+ } |
+ |
+ emit_mat(canvas, mat); |
+ emit_clip(canvas, clip); |
+ emit_mat(canvas, mat); |
+ emit_clip(canvas, clip); |
+ |
+ for (int i = 0; i < accumulatedClips; ++i) { |
+ add_clip(clip, mat, expected); |
+ add_clip(clip, mat, expected); |
+ } |
+ add_mat(mat, expected); |
+} |
+ |
+// Emit: |
+// matrix |
+// clip |
+// clip |
+// This tests accumulation of clips in same transform state. It also tests pushing |
+// of the matrix across both the clips. |
+static void emit_mat_clip_clip(SkCanvas* canvas, MatType mat, ClipType clip, |
+ DrawOpType draw, SkTDArray<DrawType>* expected, |
+ int accumulatedClips) { |
+ if (kNone_DrawOpType == draw) { |
+ return; |
+ } |
+ |
+ emit_mat(canvas, mat); |
+ emit_clip(canvas, clip); |
+ emit_clip(canvas, clip); |
+ |
+ for (int i = 0; i < accumulatedClips; ++i) { |
+ add_clip(clip, mat, expected); |
+ add_clip(clip, mat, expected); |
+ } |
+ add_mat(mat, expected); |
+} |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+// Emit: |
+// matrix & clip calls |
+// draw op |
+static void emit_body0(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, |
+ ClipType clip, DrawOpType draw, |
+ SkTDArray<DrawType>* expected, int accumulatedClips) { |
+ bool needsSaveRestore = kNone_DrawOpType != draw && |
+ (kNone_MatType != mat || kNone_ClipType != clip); |
+ |
+ if (needsSaveRestore) { |
+ *expected->append() = SAVE; |
+ } |
+ (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1); |
+ emit_draw(canvas, draw, expected); |
+ if (needsSaveRestore) { |
+ *expected->append() = RESTORE; |
+ } |
+} |
+ |
+// Emit: |
+// matrix & clip calls |
+// draw op |
+// matrix & clip calls |
+// draw op |
+static void emit_body1(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, |
+ ClipType clip, DrawOpType draw, |
+ SkTDArray<DrawType>* expected, int accumulatedClips) { |
+ bool needsSaveRestore = kNone_DrawOpType != draw && |
+ (kNone_MatType != mat || kNone_ClipType != clip); |
+ |
+ if (needsSaveRestore) { |
+ *expected->append() = SAVE; |
+ } |
+ (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+1); |
+ emit_draw(canvas, draw, expected); |
+ if (needsSaveRestore) { |
+ *expected->append() = RESTORE; |
+ *expected->append() = SAVE; |
+ } |
+ (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2); |
+ emit_draw(canvas, draw, expected); |
+ if (needsSaveRestore) { |
+ *expected->append() = RESTORE; |
+ } |
+} |
+ |
+// Emit: |
+// matrix & clip calls |
+// SaveLayer |
+// matrix & clip calls |
+// draw op |
+// Restore |
+static void emit_body2(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, |
+ ClipType clip, DrawOpType draw, |
+ SkTDArray<DrawType>* expected, int accumulatedClips) { |
+ bool needsSaveRestore = kNone_DrawOpType != draw && |
+ (kNone_MatType != mat || kNone_ClipType != clip); |
+ |
+ if (needsSaveRestore) { |
+ *expected->append() = SAVE_LAYER; |
+ } |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops |
+ // TODO: widen testing to exercise saveLayer's parameters |
+ canvas->saveLayer(NULL, NULL); |
+ if (needsSaveRestore) { |
+ *expected->append() = SAVE; |
+ } |
+ (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2); |
+ emit_draw(canvas, draw, expected); |
+ if (needsSaveRestore) { |
+ *expected->append() = RESTORE; |
+ } |
+ canvas->restore(); |
+ if (needsSaveRestore) { |
+ *expected->append() = RESTORE; |
+ } |
+} |
+ |
+// Emit: |
+// matrix & clip calls |
+// SaveLayer |
+// matrix & clip calls |
+// SaveLayer |
+// matrix & clip calls |
+// draw op |
+// Restore |
+// matrix & clip calls (will be ignored) |
+// Restore |
+static void emit_body3(SkCanvas* canvas, PFEmitMC emitMC, MatType mat, |
+ ClipType clip, DrawOpType draw, |
+ SkTDArray<DrawType>* expected, int accumulatedClips) { |
+ bool needsSaveRestore = kNone_DrawOpType != draw && |
+ (kNone_MatType != mat || kNone_ClipType != clip); |
+ |
+ // This saveLayer will always be forced b.c. we currently can't tell |
+ // ahead of time if it will be empty (see comment in SkMatrixClipStateMgr::save) |
+ *expected->append() = SAVE_LAYER; |
+ |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops |
+ // TODO: widen testing to exercise saveLayer's parameters |
+ canvas->saveLayer(NULL, NULL); |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops |
+ if (needsSaveRestore) { |
+ *expected->append() = SAVE_LAYER; |
+ } |
+ // TODO: widen testing to exercise saveLayer's parameters |
+ canvas->saveLayer(NULL, NULL); |
+ if (needsSaveRestore) { |
+ *expected->append() = SAVE; |
+ } |
+ (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+3); |
+ emit_draw(canvas, draw, expected); |
+ if (needsSaveRestore) { |
+ *expected->append() = RESTORE; |
+ } |
+ canvas->restore(); |
+ if (needsSaveRestore) { |
+ *expected->append() = RESTORE; |
+ } |
+ canvas->restore(); |
+ |
+ // required to match forced SAVE_LAYER |
+ *expected->append() = RESTORE; |
+} |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+// Emit: |
+// Save |
+// some body |
+// Restore |
+// Note: the outer save/restore are provided by beginRecording/endRecording |
+static void emit_struct0(SkCanvas* canvas, |
+ PFEmitMC emitMC, MatType mat, ClipType clip, |
+ PFEmitBody emitBody, DrawOpType draw, |
+ SkTDArray<DrawType>* expected) { |
+ (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 0); |
+} |
+ |
+// Emit: |
+// Save |
+// matrix & clip calls |
+// Save |
+// some body |
+// Restore |
+// matrix & clip calls (will be ignored) |
+// Restore |
+// Note: the outer save/restore are provided by beginRecording/endRecording |
+static void emit_struct1(SkCanvas* canvas, |
+ PFEmitMC emitMC, MatType mat, ClipType clip, |
+ PFEmitBody emitBody, DrawOpType draw, |
+ SkTDArray<DrawType>* expected) { |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops |
+ canvas->save(); |
+ (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1); |
+ canvas->restore(); |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get removed |
+} |
+ |
+// Emit: |
+// Save |
+// matrix & clip calls |
+// Save |
+// some body |
+// Restore |
+// Save |
+// some body |
+// Restore |
+// matrix & clip calls (will be ignored) |
+// Restore |
+// Note: the outer save/restore are provided by beginRecording/endRecording |
+static void emit_struct2(SkCanvas* canvas, |
+ PFEmitMC emitMC, MatType mat, ClipType clip, |
+ PFEmitBody emitBody, DrawOpType draw, |
+ SkTDArray<DrawType>* expected) { |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get fused into later ops |
+ canvas->save(); |
+ (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1); |
+ canvas->restore(); |
+ canvas->save(); |
+ (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1); |
+ canvas->restore(); |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get removed |
+} |
+ |
+// Emit: |
+// Save |
+// matrix & clip calls |
+// Save |
+// some body |
+// Restore |
+// Save |
+// matrix & clip calls |
+// Save |
+// some body |
+// Restore |
+// Restore |
+// matrix & clip calls (will be ignored) |
+// Restore |
+// Note: the outer save/restore are provided by beginRecording/endRecording |
+static void emit_struct3(SkCanvas* canvas, |
+ PFEmitMC emitMC, MatType mat, ClipType clip, |
+ PFEmitBody emitBody, DrawOpType draw, |
+ SkTDArray<DrawType>* expected) { |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get fused into later ops |
+ canvas->save(); |
+ (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 1); |
+ canvas->restore(); |
+ canvas->save(); |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 1); // these will get fused into later ops |
+ canvas->save(); |
+ (*emitBody)(canvas, emitMC, mat, clip, draw, expected, 2); |
+ canvas->restore(); |
+ canvas->restore(); |
+ (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these will get removed |
+} |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+#ifdef COLLAPSE_MATRIX_CLIP_STATE |
+static void print(const SkTDArray<DrawType>& expected, const SkTDArray<DrawType>& actual) { |
+ SkDebugf("\n\nexpected %d --- actual %d\n", expected.count(), actual.count()); |
+ int max = SkMax32(expected.count(), actual.count()); |
+ |
+ for (int i = 0; i < max; ++i) { |
+ if (i < expected.count()) { |
+ SkDebugf("%16s, ", SkDrawCommand::GetCommandString(expected[i])); |
+ } else { |
+ SkDebugf("%16s, ", " "); |
+ } |
+ |
+ if (i < actual.count()) { |
+ SkDebugf("%s\n", SkDrawCommand::GetCommandString(actual[i])); |
+ } else { |
+ SkDebugf("\n"); |
+ } |
+ } |
+ SkDebugf("\n\n"); |
+ SkASSERT(0); |
+} |
+#endif |
+ |
+static void test_collapse(skiatest::Reporter* reporter) { |
+ PFEmitStruct gStructure[] = { emit_struct0, emit_struct1, emit_struct2, emit_struct3 }; |
+ PFEmitBody gBody[] = { emit_body0, emit_body1, emit_body2, emit_body3 }; |
+ PFEmitMC gMCs[] = { emit_clip_and_mat, emit_mat_and_clip, |
+ emit_double_mat_and_clip, emit_mat_clip_clip }; |
+ |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gStructure); ++i) { |
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gBody); ++j) { |
+ for (size_t k = 0; k < SK_ARRAY_COUNT(gMCs); ++k) { |
+ for (int l = 0; l < kMatTypeCount; ++l) { |
+ for (int m = 0; m < kClipTypeCount; ++m) { |
+ for (int n = 0; n < kDrawOpTypeCount; ++n) { |
+#ifdef COLLAPSE_MATRIX_CLIP_STATE |
+ static int testID = -1; |
+ ++testID; |
+ if (testID < -1) { |
+ continue; |
+ } |
+#endif |
+ |
+ SkTDArray<DrawType> expected, actual; |
+ |
+ SkPicture picture; |
+ |
+ // Note: beginRecording/endRecording add a save/restore pair |
+ SkCanvas* canvas = picture.beginRecording(100, 100); |
+ (*gStructure[i])(canvas, |
+ gMCs[k], |
+ (MatType) l, |
+ (ClipType) m, |
+ gBody[j], |
+ (DrawOpType) n, |
+ &expected); |
+ picture.endRecording(); |
+ |
+ gets_ops(picture, &actual); |
+ |
+ REPORTER_ASSERT(reporter, expected.count() == actual.count()); |
+ |
+ if (expected.count() != actual.count()) { |
+#ifdef COLLAPSE_MATRIX_CLIP_STATE |
+ print(expected, actual); |
+#endif |
+ continue; |
+ } |
+ |
+ for (int i = 0; i < expected.count(); ++i) { |
+ REPORTER_ASSERT(reporter, expected[i] == actual[i]); |
+#ifdef COLLAPSE_MATRIX_CLIP_STATE |
+ if (expected[i] != actual[i]) { |
+ print(expected, actual); |
+ } |
+#endif |
+ break; |
+ } |
+ } |
+ } |
+ } |
+ } |
+ } |
+ } |
+} |
+ |
+DEF_TEST(MatrixClipCollapse, reporter) { |
+ test_collapse(reporter); |
+} |
+ |
+#endif |
Property changes on: tests\MatrixClipCollapseTest.cpp |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |