1cb93a386Sopenharmony_ci// Copyright 2021 Google LLC. 2cb93a386Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3cb93a386Sopenharmony_ci 4cb93a386Sopenharmony_ci#include "experimental/sorttoy/Cmds.h" 5cb93a386Sopenharmony_ci#include "experimental/sorttoy/Fake.h" 6cb93a386Sopenharmony_ci#include "experimental/sorttoy/SortKey.h" 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 9cb93a386Sopenharmony_ci#include "include/core/SkGraphics.h" 10cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 11cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 14cb93a386Sopenharmony_ci#include "src/utils/SkOSPath.h" 15cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 16cb93a386Sopenharmony_ci#include "tools/flags/CommandLineFlags.h" 17cb93a386Sopenharmony_ci#include "tools/gpu/GrContextFactory.h" 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#include <algorithm> 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci/* 22cb93a386Sopenharmony_ci * Questions this is trying to answer: 23cb93a386Sopenharmony_ci * How to handle saveLayers (in w/ everything or separate) 24cb93a386Sopenharmony_ci * How to handle blurs & other off screen draws 25cb93a386Sopenharmony_ci * How to handle clipping 26cb93a386Sopenharmony_ci * How does sorting stack up against buckets 27cb93a386Sopenharmony_ci * How does creating batches interact w/ the sorting 28cb93a386Sopenharmony_ci * How does batching work w/ text 29cb93a386Sopenharmony_ci * How does text (esp. atlasing) work at all 30cb93a386Sopenharmony_ci * Batching quality vs. existing 31cb93a386Sopenharmony_ci * Memory churn/overhead vs existing (esp. wrt batching) 32cb93a386Sopenharmony_ci * gpu vs cpu boundedness 33cb93a386Sopenharmony_ci * 34cb93a386Sopenharmony_ci * Futher Questions: 35cb93a386Sopenharmony_ci * How can we collect uniforms & not store the fps -- seems complicated 36cb93a386Sopenharmony_ci * Do all the blend modes (esp. advanced work front-to-back)? 37cb93a386Sopenharmony_ci * skgpu::v2 perf vs. skgpu::v1 perf 38cb93a386Sopenharmony_ci * Can we prepare any of the saveLayers or off-screen draw render passes in parallel? 39cb93a386Sopenharmony_ci * 40cb93a386Sopenharmony_ci * Small potatoes: 41cb93a386Sopenharmony_ci * Incorporate CTM into the simulator 42cb93a386Sopenharmony_ci */ 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci/* 45cb93a386Sopenharmony_ci * How does this all work: 46cb93a386Sopenharmony_ci * 47cb93a386Sopenharmony_ci * Each test is specified by a set of RectCmds (which have a unique ID and carry their material 48cb93a386Sopenharmony_ci * and MC state info) along with the order they are expected to be drawn in with the skgpu::v2. 49cb93a386Sopenharmony_ci * 50cb93a386Sopenharmony_ci * To generate an expected image, the RectCmds are replayed into an SkCanvas in the order 51cb93a386Sopenharmony_ci * provided. 52cb93a386Sopenharmony_ci * 53cb93a386Sopenharmony_ci * For the actual (v2) image, the RectCmds are replayed into a FakeCanvas - preserving the 54cb93a386Sopenharmony_ci * unique ID of the RectCmd. The FakeCanvas creates new RectCmd objects, sorts them using 55cb93a386Sopenharmony_ci * the SortKey and then performs a kludgey z-buffered rasterization. The FakeCanvas also 56cb93a386Sopenharmony_ci * preserves the RectCmd order it ultimately used for its rendering and this can be compared 57cb93a386Sopenharmony_ci * with the expected order from the test. 58cb93a386Sopenharmony_ci * 59cb93a386Sopenharmony_ci * The use of the RectCmds to create the tests is a mere convenience to avoid creating a 60cb93a386Sopenharmony_ci * separate representation of the desired draws. 61cb93a386Sopenharmony_ci * 62cb93a386Sopenharmony_ci *************************** 63cb93a386Sopenharmony_ci * Here are some of the simplifying assumptions of this simulation (and their justification): 64cb93a386Sopenharmony_ci * 65cb93a386Sopenharmony_ci * Only SkIRects are used for draws and clips - since MSAA should be taking care of AA for us in 66cb93a386Sopenharmony_ci * the skgpu::v2 we don't really need SkRects. This also greatly simplifies the z-buffered 67cb93a386Sopenharmony_ci * rasterization. 68cb93a386Sopenharmony_ci * 69cb93a386Sopenharmony_ci ************************** 70cb93a386Sopenharmony_ci * Areas for improvement: 71cb93a386Sopenharmony_ci * We should add strokes since there are two distinct drawing methods in the skgpu::v2 (fill v. 72cb93a386Sopenharmony_ci * stroke) 73cb93a386Sopenharmony_ci */ 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ciusing sk_gpu_test::GrContextFactory; 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_cistatic DEFINE_string2(writePath, w, "", "If set, write bitmaps here as .pngs."); 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_cistatic void exitf(const char* format, ...) { 80cb93a386Sopenharmony_ci va_list args; 81cb93a386Sopenharmony_ci va_start(args, format); 82cb93a386Sopenharmony_ci vfprintf(stderr, format, args); 83cb93a386Sopenharmony_ci va_end(args); 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci exit(1); 86cb93a386Sopenharmony_ci} 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_cistatic void save_files(int testID, Shape s, const SkBitmap& expected, const SkBitmap& actual) { 89cb93a386Sopenharmony_ci if (FLAGS_writePath.isEmpty()) { 90cb93a386Sopenharmony_ci return; 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci const char* dir = FLAGS_writePath[0]; 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci SkString path = SkOSPath::Join(dir, s == Shape::kRect ? "rect-expected" : "oval-expected"); 96cb93a386Sopenharmony_ci path.appendU32(testID); 97cb93a386Sopenharmony_ci path.append(".png"); 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci if (!sk_mkdir(dir)) { 100cb93a386Sopenharmony_ci exitf("failed to create directory for png \"%s\"", path.c_str()); 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci if (!ToolUtils::EncodeImageToFile(path.c_str(), expected, SkEncodedImageFormat::kPNG, 100)) { 103cb93a386Sopenharmony_ci exitf("failed to save png to \"%s\"", path.c_str()); 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci path = SkOSPath::Join(dir, s == Shape::kRect ? "rect-actual" : "oval-actual"); 107cb93a386Sopenharmony_ci path.appendU32(testID); 108cb93a386Sopenharmony_ci path.append(".png"); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci if (!ToolUtils::EncodeImageToFile(path.c_str(), actual, SkEncodedImageFormat::kPNG, 100)) { 111cb93a386Sopenharmony_ci exitf("failed to save png to \"%s\"", path.c_str()); 112cb93a386Sopenharmony_ci } 113cb93a386Sopenharmony_ci} 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci// Exercise basic SortKey behavior 116cb93a386Sopenharmony_cistatic void key_test() { 117cb93a386Sopenharmony_ci SortKey k; 118cb93a386Sopenharmony_ci SkASSERT(!k.transparent()); 119cb93a386Sopenharmony_ci SkASSERT(k.depth() == 0); 120cb93a386Sopenharmony_ci SkASSERT(k.material() == 0); 121cb93a386Sopenharmony_ci// k.dump(); 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci SortKey k1(false, 1, 3); 124cb93a386Sopenharmony_ci SkASSERT(!k1.transparent()); 125cb93a386Sopenharmony_ci SkASSERT(k1.depth() == 1); 126cb93a386Sopenharmony_ci SkASSERT(k1.material() == 3); 127cb93a386Sopenharmony_ci// k1.dump(); 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci SortKey k2(true, 2, 1); 130cb93a386Sopenharmony_ci SkASSERT(k2.transparent()); 131cb93a386Sopenharmony_ci SkASSERT(k2.depth() == 2); 132cb93a386Sopenharmony_ci SkASSERT(k2.material() == 1); 133cb93a386Sopenharmony_ci// k2.dump(); 134cb93a386Sopenharmony_ci} 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_cistatic void check_state(FakeMCBlob* actualState, 137cb93a386Sopenharmony_ci SkIPoint expectedCTM, 138cb93a386Sopenharmony_ci const std::vector<SkIRect>& expectedClips) { 139cb93a386Sopenharmony_ci SkASSERT(actualState->ctm() == expectedCTM); 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci int i = 0; 142cb93a386Sopenharmony_ci auto states = actualState->mcStates(); 143cb93a386Sopenharmony_ci for (auto& s : states) { 144cb93a386Sopenharmony_ci for (const sk_sp<ClipCmd>& c : s.cmds()) { 145cb93a386Sopenharmony_ci SkAssertResult(i < (int) expectedClips.size()); 146cb93a386Sopenharmony_ci SkAssertResult(c->rect() == expectedClips[i]); 147cb93a386Sopenharmony_ci i++; 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci} 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci// Exercise the FakeMCBlob object 153cb93a386Sopenharmony_cistatic void mcstack_test() { 154cb93a386Sopenharmony_ci const SkIRect r { 0, 0, 10, 10 }; 155cb93a386Sopenharmony_ci const SkIPoint s1Trans { 10, 10 }; 156cb93a386Sopenharmony_ci const SkIPoint s2TransA { -5, -2 }; 157cb93a386Sopenharmony_ci const SkIPoint s2TransB { -3, -1 }; 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci const std::vector<SkIRect> expectedS0Clips; 160cb93a386Sopenharmony_ci const std::vector<SkIRect> expectedS1Clips { 161cb93a386Sopenharmony_ci r.makeOffset(s1Trans) 162cb93a386Sopenharmony_ci }; 163cb93a386Sopenharmony_ci const std::vector<SkIRect> expectedS2aClips { 164cb93a386Sopenharmony_ci r.makeOffset(s1Trans), 165cb93a386Sopenharmony_ci r.makeOffset(s2TransA) 166cb93a386Sopenharmony_ci }; 167cb93a386Sopenharmony_ci const std::vector<SkIRect> expectedS2bClips { 168cb93a386Sopenharmony_ci r.makeOffset(s1Trans), 169cb93a386Sopenharmony_ci r.makeOffset(s2TransA), 170cb93a386Sopenharmony_ci r.makeOffset(s2TransA + s2TransB) 171cb93a386Sopenharmony_ci }; 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci //---------------- 174cb93a386Sopenharmony_ci FakeStateTracker s; 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci auto state0 = s.snapState(); 177cb93a386Sopenharmony_ci // The initial state should have no translation & no clip 178cb93a386Sopenharmony_ci check_state(state0.get(), { 0, 0 }, expectedS0Clips); 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci //---------------- 181cb93a386Sopenharmony_ci s.push(); 182cb93a386Sopenharmony_ci s.translate(s1Trans); 183cb93a386Sopenharmony_ci s.clip(sk_make_sp<ClipCmd>(ID(1), Shape::kRect, r)); 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci auto state1 = s.snapState(); 186cb93a386Sopenharmony_ci check_state(state1.get(), s1Trans, expectedS1Clips); 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci //---------------- 189cb93a386Sopenharmony_ci s.push(); 190cb93a386Sopenharmony_ci s.translate(s2TransA); 191cb93a386Sopenharmony_ci s.clip(sk_make_sp<ClipCmd>(ID(2), Shape::kRect, r)); 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci auto state2a = s.snapState(); 194cb93a386Sopenharmony_ci check_state(state2a.get(), s1Trans + s2TransA, expectedS2aClips); 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_ci s.translate(s2TransB); 197cb93a386Sopenharmony_ci s.clip(sk_make_sp<ClipCmd>(ID(3), Shape::kRect, r)); 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci auto state2b = s.snapState(); 200cb93a386Sopenharmony_ci check_state(state2b.get(), s1Trans + s2TransA + s2TransB, expectedS2bClips); 201cb93a386Sopenharmony_ci SkASSERT(state2a != state2b); 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ci //---------------- 204cb93a386Sopenharmony_ci s.pop(PaintersOrder(1)); 205cb93a386Sopenharmony_ci auto state3 = s.snapState(); 206cb93a386Sopenharmony_ci check_state(state3.get(), s1Trans, expectedS1Clips); 207cb93a386Sopenharmony_ci SkASSERT(state1 == state3); 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_ci //---------------- 210cb93a386Sopenharmony_ci s.pop(PaintersOrder(2)); 211cb93a386Sopenharmony_ci auto state4 = s.snapState(); 212cb93a386Sopenharmony_ci check_state(state4.get(), { 0, 0 }, expectedS0Clips); 213cb93a386Sopenharmony_ci SkASSERT(state0 == state4); 214cb93a386Sopenharmony_ci} 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_cistatic void check_order(int testID, 217cb93a386Sopenharmony_ci const std::vector<ID>& actualOrder, 218cb93a386Sopenharmony_ci const std::vector<ID>& expectedOrder) { 219cb93a386Sopenharmony_ci if (expectedOrder.size() != actualOrder.size()) { 220cb93a386Sopenharmony_ci exitf("Op count mismatch in test %d. Expected %d - got %d\n", 221cb93a386Sopenharmony_ci testID, 222cb93a386Sopenharmony_ci expectedOrder.size(), 223cb93a386Sopenharmony_ci actualOrder.size()); 224cb93a386Sopenharmony_ci } 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci if (expectedOrder != actualOrder) { 227cb93a386Sopenharmony_ci SkDebugf("order mismatch in test %d:\n", testID); 228cb93a386Sopenharmony_ci SkDebugf("E %zu: ", expectedOrder.size()); 229cb93a386Sopenharmony_ci for (auto t : expectedOrder) { 230cb93a386Sopenharmony_ci SkDebugf("%d", t.toInt()); 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci SkDebugf("\n"); 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ci SkDebugf("A %zu: ", actualOrder.size()); 235cb93a386Sopenharmony_ci for (auto t : actualOrder) { 236cb93a386Sopenharmony_ci SkDebugf("%d", t.toInt()); 237cb93a386Sopenharmony_ci } 238cb93a386Sopenharmony_ci SkDebugf("\n"); 239cb93a386Sopenharmony_ci } 240cb93a386Sopenharmony_ci} 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_citypedef int (*PFTest)(std::vector<sk_sp<Cmd>>* test, 243cb93a386Sopenharmony_ci Shape shape, 244cb93a386Sopenharmony_ci std::vector<ID>* expectedOrder); 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_cistatic void sort_test(PFTest testcase) { 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci for (Shape s : { Shape::kRect, Shape::kOval }) { 249cb93a386Sopenharmony_ci std::vector<sk_sp<Cmd>> test; 250cb93a386Sopenharmony_ci std::vector<ID> expectedOrder; 251cb93a386Sopenharmony_ci int testID = testcase(&test, s, &expectedOrder); 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ci SkBitmap expectedBM; 255cb93a386Sopenharmony_ci expectedBM.allocPixels(SkImageInfo::MakeN32Premul(256, 256)); 256cb93a386Sopenharmony_ci expectedBM.eraseColor(SK_ColorBLACK); 257cb93a386Sopenharmony_ci SkCanvas real(expectedBM); 258cb93a386Sopenharmony_ci 259cb93a386Sopenharmony_ci SkBitmap actualBM; 260cb93a386Sopenharmony_ci actualBM.allocPixels(SkImageInfo::MakeN32Premul(256, 256)); 261cb93a386Sopenharmony_ci actualBM.eraseColor(SK_ColorBLACK); 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_ci FakeCanvas fake(actualBM); 264cb93a386Sopenharmony_ci for (const sk_sp<Cmd>& c : test) { 265cb93a386Sopenharmony_ci c->execute(&fake); 266cb93a386Sopenharmony_ci c->execute(&real); 267cb93a386Sopenharmony_ci } 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_ci fake.finalize(); 270cb93a386Sopenharmony_ci 271cb93a386Sopenharmony_ci std::vector<ID> actualOrder = fake.getOrder(); 272cb93a386Sopenharmony_ci check_order(testID, actualOrder, expectedOrder); 273cb93a386Sopenharmony_ci 274cb93a386Sopenharmony_ci save_files(testID, s, expectedBM, actualBM); 275cb93a386Sopenharmony_ci } 276cb93a386Sopenharmony_ci} 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_ci// Simple test - green rect should appear atop the red rect 279cb93a386Sopenharmony_cistatic int test1(std::vector<sk_sp<Cmd>>* test, 280cb93a386Sopenharmony_ci Shape shape, 281cb93a386Sopenharmony_ci std::vector<ID>* expectedOrder) { 282cb93a386Sopenharmony_ci // front-to-back order bc all opaque 283cb93a386Sopenharmony_ci expectedOrder->push_back(ID(1)); 284cb93a386Sopenharmony_ci expectedOrder->push_back(ID(0)); 285cb93a386Sopenharmony_ci 286cb93a386Sopenharmony_ci //--------------------------------------------------------------------------------------------- 287cb93a386Sopenharmony_ci test->push_back(sk_make_sp<SaveCmd>()); 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci SkIRect r{0, 0, 100, 100}; 290cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(0), shape, r.makeOffset(8, 8), FakePaint(SK_ColorRED))); 291cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(1), shape, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN))); 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci test->push_back(sk_make_sp<RestoreCmd>()); 294cb93a386Sopenharmony_ci return 1; 295cb93a386Sopenharmony_ci} 296cb93a386Sopenharmony_ci 297cb93a386Sopenharmony_ci// Simple test - blue rect atop green rect atop red rect 298cb93a386Sopenharmony_cistatic int test2(std::vector<sk_sp<Cmd>>* test, 299cb93a386Sopenharmony_ci Shape shape, 300cb93a386Sopenharmony_ci std::vector<ID>* expectedOrder) { 301cb93a386Sopenharmony_ci // front-to-back order bc all opaque 302cb93a386Sopenharmony_ci expectedOrder->push_back(ID(2)); 303cb93a386Sopenharmony_ci expectedOrder->push_back(ID(1)); 304cb93a386Sopenharmony_ci expectedOrder->push_back(ID(0)); 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci //--------------------------------------------------------------------------------------------- 307cb93a386Sopenharmony_ci test->push_back(sk_make_sp<SaveCmd>()); 308cb93a386Sopenharmony_ci 309cb93a386Sopenharmony_ci SkIRect r{0, 0, 100, 100}; 310cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(0), shape, r.makeOffset(8, 8), FakePaint(SK_ColorRED))); 311cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(1), shape, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN))); 312cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(2), shape, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE))); 313cb93a386Sopenharmony_ci 314cb93a386Sopenharmony_ci test->push_back(sk_make_sp<RestoreCmd>()); 315cb93a386Sopenharmony_ci return 2; 316cb93a386Sopenharmony_ci} 317cb93a386Sopenharmony_ci 318cb93a386Sopenharmony_ci// Transparency test - opaque blue rect atop transparent green rect atop opaque red rect 319cb93a386Sopenharmony_cistatic int test3(std::vector<sk_sp<Cmd>>* test, 320cb93a386Sopenharmony_ci Shape shape, 321cb93a386Sopenharmony_ci std::vector<ID>* expectedOrder) { 322cb93a386Sopenharmony_ci // opaque draws are first and are front-to-back. Transparent draw is last. 323cb93a386Sopenharmony_ci expectedOrder->push_back(ID(2)); 324cb93a386Sopenharmony_ci expectedOrder->push_back(ID(0)); 325cb93a386Sopenharmony_ci expectedOrder->push_back(ID(1)); 326cb93a386Sopenharmony_ci 327cb93a386Sopenharmony_ci //--------------------------------------------------------------------------------------------- 328cb93a386Sopenharmony_ci test->push_back(sk_make_sp<SaveCmd>()); 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_ci SkIRect r{0, 0, 100, 100}; 331cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(0), shape, r.makeOffset(8, 8), FakePaint(SK_ColorRED))); 332cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(1), shape, r.makeOffset(48, 48), FakePaint(0x8000FF00))); 333cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(2), shape, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE))); 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_ci test->push_back(sk_make_sp<RestoreCmd>()); 336cb93a386Sopenharmony_ci return 3; 337cb93a386Sopenharmony_ci} 338cb93a386Sopenharmony_ci 339cb93a386Sopenharmony_ci// Multi-transparency test - transparent blue rect atop transparent green rect atop 340cb93a386Sopenharmony_ci// transparent red rect 341cb93a386Sopenharmony_cistatic int test4(std::vector<sk_sp<Cmd>>* test, 342cb93a386Sopenharmony_ci Shape shape, 343cb93a386Sopenharmony_ci std::vector<ID>* expectedOrder) { 344cb93a386Sopenharmony_ci // All in back-to-front order bc they're all transparent 345cb93a386Sopenharmony_ci expectedOrder->push_back(ID(0)); 346cb93a386Sopenharmony_ci expectedOrder->push_back(ID(1)); 347cb93a386Sopenharmony_ci expectedOrder->push_back(ID(2)); 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_ci //--------------------------------------------------------------------------------------------- 350cb93a386Sopenharmony_ci test->push_back(sk_make_sp<SaveCmd>()); 351cb93a386Sopenharmony_ci 352cb93a386Sopenharmony_ci SkIRect r{0, 0, 100, 100}; 353cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(0), shape, r.makeOffset(8, 8), FakePaint(0x80FF0000))); 354cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(1), shape, r.makeOffset(48, 48), FakePaint(0x8000FF00))); 355cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(2), shape, r.makeOffset(98, 98), FakePaint(0x800000FF))); 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci test->push_back(sk_make_sp<RestoreCmd>()); 358cb93a386Sopenharmony_ci return 4; 359cb93a386Sopenharmony_ci} 360cb93a386Sopenharmony_ci 361cb93a386Sopenharmony_ci// Multiple opaque materials test 362cb93a386Sopenharmony_ci// All opaque: 363cb93a386Sopenharmony_ci// normal1, linear1, radial1, normal2, linear2, radial2 364cb93a386Sopenharmony_ci// Which gets sorted to: 365cb93a386Sopenharmony_ci// normal2, normal1, linear2, linear1, radial2, radial1 366cb93a386Sopenharmony_ci// So, front to back w/in each material type. 367cb93a386Sopenharmony_cistatic int test5(std::vector<sk_sp<Cmd>>* test, 368cb93a386Sopenharmony_ci Shape shape, 369cb93a386Sopenharmony_ci std::vector<ID>* expectedOrder) { 370cb93a386Sopenharmony_ci // Note: This pushes sorting by material above sorting by Z. Thus we'll get less front to 371cb93a386Sopenharmony_ci // back benefit. 372cb93a386Sopenharmony_ci expectedOrder->push_back(ID(3)); 373cb93a386Sopenharmony_ci expectedOrder->push_back(ID(0)); 374cb93a386Sopenharmony_ci expectedOrder->push_back(ID(4)); 375cb93a386Sopenharmony_ci expectedOrder->push_back(ID(1)); 376cb93a386Sopenharmony_ci expectedOrder->push_back(ID(5)); 377cb93a386Sopenharmony_ci expectedOrder->push_back(ID(2)); 378cb93a386Sopenharmony_ci 379cb93a386Sopenharmony_ci //--------------------------------------------------------------------------------------------- 380cb93a386Sopenharmony_ci test->push_back(sk_make_sp<SaveCmd>()); 381cb93a386Sopenharmony_ci 382cb93a386Sopenharmony_ci FakePaint p; 383cb93a386Sopenharmony_ci 384cb93a386Sopenharmony_ci SkIRect r{0, 0, 100, 100}; 385cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(0), shape, r.makeOffset(8, 8), FakePaint(SK_ColorRED))); 386cb93a386Sopenharmony_ci p.setLinear(SK_ColorGREEN, SK_ColorWHITE); 387cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(1), shape, r.makeOffset(48, 48), p)); 388cb93a386Sopenharmony_ci p.setRadial(SK_ColorBLUE, SK_ColorBLACK); 389cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(2), shape, r.makeOffset(98, 98), p)); 390cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(3), shape, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN))); 391cb93a386Sopenharmony_ci p.setLinear(SK_ColorMAGENTA, SK_ColorWHITE); 392cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(4), shape, r.makeOffset(148, 8), p)); 393cb93a386Sopenharmony_ci p.setRadial(SK_ColorYELLOW, SK_ColorBLACK); 394cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(5), shape, r.makeOffset(8, 148), p)); 395cb93a386Sopenharmony_ci 396cb93a386Sopenharmony_ci test->push_back(sk_make_sp<RestoreCmd>()); 397cb93a386Sopenharmony_ci return 5; 398cb93a386Sopenharmony_ci} 399cb93a386Sopenharmony_ci 400cb93a386Sopenharmony_ci// simple clipping test - two shapes w/ 1 clip of the opposite shape 401cb93a386Sopenharmony_cistatic int test6(std::vector<sk_sp<Cmd>>* test, 402cb93a386Sopenharmony_ci Shape shape, 403cb93a386Sopenharmony_ci std::vector<ID>* expectedOrder) { 404cb93a386Sopenharmony_ci // The expected is front to back after the clip 405cb93a386Sopenharmony_ci expectedOrder->push_back(ID(2)); 406cb93a386Sopenharmony_ci expectedOrder->push_back(ID(1)); 407cb93a386Sopenharmony_ci 408cb93a386Sopenharmony_ci Shape clipShape = shape == Shape::kRect ? Shape::kOval : Shape::kRect; 409cb93a386Sopenharmony_ci //--------------------------------------------------------------------------------------------- 410cb93a386Sopenharmony_ci test->push_back(sk_make_sp<SaveCmd>()); 411cb93a386Sopenharmony_ci 412cb93a386Sopenharmony_ci test->push_back(sk_make_sp<ClipCmd>(ID(0), clipShape, SkIRect::MakeXYWH(28, 28, 40, 40))); 413cb93a386Sopenharmony_ci 414cb93a386Sopenharmony_ci SkIRect r{0, 0, 100, 100}; 415cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(1), shape, r.makeOffset(8, 8), FakePaint(SK_ColorRED))); 416cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(2), shape, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN))); 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci test->push_back(sk_make_sp<RestoreCmd>()); 419cb93a386Sopenharmony_ci return 6; 420cb93a386Sopenharmony_ci} 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci// more complicated clipping w/ opaque draws -> should reorder 423cb93a386Sopenharmony_cistatic int test7(std::vector<sk_sp<Cmd>>* test, 424cb93a386Sopenharmony_ci Shape shape, 425cb93a386Sopenharmony_ci std::vector<ID>* expectedOrder) { 426cb93a386Sopenharmony_ci // The expected is front to back modulated by the two clip states 427cb93a386Sopenharmony_ci expectedOrder->push_back(ID(7)); 428cb93a386Sopenharmony_ci expectedOrder->push_back(ID(6)); 429cb93a386Sopenharmony_ci expectedOrder->push_back(ID(2)); 430cb93a386Sopenharmony_ci expectedOrder->push_back(ID(1)); 431cb93a386Sopenharmony_ci 432cb93a386Sopenharmony_ci expectedOrder->push_back(ID(5)); 433cb93a386Sopenharmony_ci expectedOrder->push_back(ID(4)); 434cb93a386Sopenharmony_ci 435cb93a386Sopenharmony_ci Shape clipShape = shape == Shape::kRect ? Shape::kOval : Shape::kRect; 436cb93a386Sopenharmony_ci //--------------------------------------------------------------------------------------------- 437cb93a386Sopenharmony_ci test->push_back(sk_make_sp<SaveCmd>()); 438cb93a386Sopenharmony_ci // select the middle third in x 439cb93a386Sopenharmony_ci test->push_back(sk_make_sp<ClipCmd>(ID(0), clipShape, SkIRect::MakeXYWH(85, 0, 86, 256))); 440cb93a386Sopenharmony_ci 441cb93a386Sopenharmony_ci SkIRect r{0, 0, 100, 100}; 442cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(1), shape, r.makeOffset(8, 8), FakePaint(SK_ColorRED))); 443cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(2), shape, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN))); 444cb93a386Sopenharmony_ci 445cb93a386Sopenharmony_ci test->push_back(sk_make_sp<SaveCmd>()); 446cb93a386Sopenharmony_ci // intersect w/ the middle third in y 447cb93a386Sopenharmony_ci test->push_back(sk_make_sp<ClipCmd>(ID(3), clipShape, SkIRect::MakeXYWH(0, 85, 256, 86))); 448cb93a386Sopenharmony_ci 449cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(4), shape, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE))); 450cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(5), shape, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN))); 451cb93a386Sopenharmony_ci 452cb93a386Sopenharmony_ci test->push_back(sk_make_sp<RestoreCmd>()); 453cb93a386Sopenharmony_ci 454cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(6), shape, r.makeOffset(148, 8), FakePaint(SK_ColorMAGENTA))); 455cb93a386Sopenharmony_ci test->push_back(sk_make_sp<DrawCmd>(ID(7), shape, r.makeOffset(8, 148), FakePaint(SK_ColorYELLOW))); 456cb93a386Sopenharmony_ci 457cb93a386Sopenharmony_ci test->push_back(sk_make_sp<RestoreCmd>()); 458cb93a386Sopenharmony_ci return 7; 459cb93a386Sopenharmony_ci} 460cb93a386Sopenharmony_ci 461cb93a386Sopenharmony_ciint main(int argc, char** argv) { 462cb93a386Sopenharmony_ci CommandLineFlags::Parse(argc, argv); 463cb93a386Sopenharmony_ci 464cb93a386Sopenharmony_ci SkGraphics::Init(); 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ci key_test(); 467cb93a386Sopenharmony_ci mcstack_test(); 468cb93a386Sopenharmony_ci sort_test(test1); 469cb93a386Sopenharmony_ci sort_test(test2); 470cb93a386Sopenharmony_ci sort_test(test3); 471cb93a386Sopenharmony_ci sort_test(test4); 472cb93a386Sopenharmony_ci sort_test(test5); 473cb93a386Sopenharmony_ci sort_test(test6); 474cb93a386Sopenharmony_ci sort_test(test7); 475cb93a386Sopenharmony_ci 476cb93a386Sopenharmony_ci return 0; 477cb93a386Sopenharmony_ci} 478