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/Fake.h" 5cb93a386Sopenharmony_ci 6cb93a386Sopenharmony_ci#include "experimental/sorttoy/Cmds.h" 7cb93a386Sopenharmony_ci#include "experimental/sorttoy/SortKey.h" 8cb93a386Sopenharmony_ci 9cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci//------------------------------------------------------------------------------------------------- 13cb93a386Sopenharmony_civoid FakeMCBlob::MCState::addClip(sk_sp<ClipCmd> clipCmd) { 14cb93a386Sopenharmony_ci clipCmd->mutate(fTrans); 15cb93a386Sopenharmony_ci fCmds.push_back(std::move(clipCmd)); 16cb93a386Sopenharmony_ci fCached = nullptr; 17cb93a386Sopenharmony_ci} 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cibool FakeMCBlob::MCState::operator==(const MCState& other) const { 20cb93a386Sopenharmony_ci if (fTrans != other.fTrans || fCmds.size() != other.fCmds.size()) { 21cb93a386Sopenharmony_ci return false; 22cb93a386Sopenharmony_ci } 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci for (size_t i = 0; i < fCmds.size(); ++i) { 25cb93a386Sopenharmony_ci if (fCmds[i]->rect() != other.fCmds[i]->rect()) { 26cb93a386Sopenharmony_ci return false; 27cb93a386Sopenharmony_ci } 28cb93a386Sopenharmony_ci } 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci return true; 31cb93a386Sopenharmony_ci} 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_civoid FakeMCBlob::MCState::aboutToBePopped(PaintersOrder paintersOrderWhenPopped) { 34cb93a386Sopenharmony_ci for (sk_sp<ClipCmd>& c : fCmds) { 35cb93a386Sopenharmony_ci c->onAboutToBePopped(paintersOrderWhenPopped); 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci} 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ciFakeMCBlob::FakeMCBlob(const std::vector<MCState>& stack) : fID(NextID()), fStack(stack) { 41cb93a386Sopenharmony_ci fScissor = SkIRect::MakeLTRB(-1000, -1000, 1000, 1000); 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci for (MCState& s : fStack) { 44cb93a386Sopenharmony_ci // xform the clip rects into device space to compute the scissor 45cb93a386Sopenharmony_ci for (const sk_sp<ClipCmd>& c : s.fCmds) { 46cb93a386Sopenharmony_ci SkASSERT(c->hasBeenMutated()); 47cb93a386Sopenharmony_ci SkIRect r = c->rect(); 48cb93a386Sopenharmony_ci r.offset(fCTM); 49cb93a386Sopenharmony_ci if (!fScissor.intersect(r)) { 50cb93a386Sopenharmony_ci fScissor.setEmpty(); 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci fCTM += s.getTrans(); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci} 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci//------------------------------------------------------------------------------------------------- 58cb93a386Sopenharmony_ci// Linearly blend between c0 & c1: 59cb93a386Sopenharmony_ci// (t == 0) -> c0 60cb93a386Sopenharmony_ci// (t == 1) -> c1 61cb93a386Sopenharmony_cistatic SkColor blend(float t, SkColor c0, SkColor c1) { 62cb93a386Sopenharmony_ci SkASSERT(t >= 0.0f && t <= 1.0f); 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci SkColor4f top = SkColor4f::FromColor(c0); 65cb93a386Sopenharmony_ci SkColor4f bot = SkColor4f::FromColor(c1); 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci SkColor4f result = { 68cb93a386Sopenharmony_ci t * bot.fR + (1.0f - t) * top.fR, 69cb93a386Sopenharmony_ci t * bot.fG + (1.0f - t) * top.fG, 70cb93a386Sopenharmony_ci t * bot.fB + (1.0f - t) * top.fB, 71cb93a386Sopenharmony_ci t * bot.fA + (1.0f - t) * top.fA 72cb93a386Sopenharmony_ci }; 73cb93a386Sopenharmony_ci return result.toSkColor(); 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ciint FakePaint::toID() const { 77cb93a386Sopenharmony_ci switch (fType) { 78cb93a386Sopenharmony_ci case Type::kNormal: return kSolidMat; 79cb93a386Sopenharmony_ci case Type::kLinear: return kLinearMat; 80cb93a386Sopenharmony_ci case Type::kRadial: return kRadialMat; 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci SkUNREACHABLE; 83cb93a386Sopenharmony_ci} 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ciSkColor FakePaint::evalColor(int x, int y) const { 86cb93a386Sopenharmony_ci switch (fType) { 87cb93a386Sopenharmony_ci case Type::kNormal: return fColor0; 88cb93a386Sopenharmony_ci case Type::kLinear: { 89cb93a386Sopenharmony_ci float t = SK_ScalarRoot2Over2 * x + SK_ScalarRoot2Over2 * y; 90cb93a386Sopenharmony_ci t /= SK_ScalarSqrt2 * 256.0f; 91cb93a386Sopenharmony_ci return blend(t, fColor0, fColor1); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci case Type::kRadial: { 94cb93a386Sopenharmony_ci x -= 128; 95cb93a386Sopenharmony_ci y -= 128; 96cb93a386Sopenharmony_ci float dist = sqrt(x*x + y*y) / 128.0f; 97cb93a386Sopenharmony_ci if (dist > 1.0f) { 98cb93a386Sopenharmony_ci return fColor0; 99cb93a386Sopenharmony_ci } else { 100cb93a386Sopenharmony_ci return blend(dist, fColor0, fColor1); 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci SkUNREACHABLE; 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci//------------------------------------------------------------------------------------------------- 108cb93a386Sopenharmony_civoid FakeDevice::save() { 109cb93a386Sopenharmony_ci fTracker.push(); 110cb93a386Sopenharmony_ci} 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_civoid FakeDevice::drawShape(ID id, PaintersOrder paintersOrder, Shape shape, SkIRect r, FakePaint p) { 113cb93a386Sopenharmony_ci sk_sp<FakeMCBlob> state = fTracker.snapState(); 114cb93a386Sopenharmony_ci SkASSERT(state); 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci sk_sp<Cmd> tmp = sk_make_sp<DrawCmd>(id, paintersOrder, shape, r, p, std::move(state)); 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci fSortedCmds.push_back(std::move(tmp)); 119cb93a386Sopenharmony_ci} 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_civoid FakeDevice::clipShape(ID id, PaintersOrder paintersOrder, Shape shape, SkIRect r) { 122cb93a386Sopenharmony_ci sk_sp<ClipCmd> tmp = sk_make_sp<ClipCmd>(id, paintersOrder, shape, r); 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci fTracker.clip(std::move(tmp)); 125cb93a386Sopenharmony_ci} 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_civoid FakeDevice::restore(PaintersOrder paintersOrderWhenPopped) { 128cb93a386Sopenharmony_ci fTracker.pop(paintersOrderWhenPopped); 129cb93a386Sopenharmony_ci} 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_civoid FakeDevice::finalize() { 132cb93a386Sopenharmony_ci SkASSERT(!fFinalized); 133cb93a386Sopenharmony_ci fFinalized = true; 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci this->sort(); 136cb93a386Sopenharmony_ci for (const sk_sp<Cmd>& c : fSortedCmds) { 137cb93a386Sopenharmony_ci c->rasterize(fZBuffer, &fBM); 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci} 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_civoid FakeDevice::getOrder(std::vector<ID>* ops) const { 142cb93a386Sopenharmony_ci SkASSERT(fFinalized); 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci for (const sk_sp<Cmd>& c : fSortedCmds) { 145cb93a386Sopenharmony_ci ops->push_back(c->id()); 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci} 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_civoid FakeDevice::sort() { 150cb93a386Sopenharmony_ci // In general we want: 151cb93a386Sopenharmony_ci // opaque draws to occur front to back (i.e., in reverse painter's order) while minimizing 152cb93a386Sopenharmony_ci // state changes due to materials 153cb93a386Sopenharmony_ci // transparent draws to occur back to front (i.e., in painter's order) 154cb93a386Sopenharmony_ci // 155cb93a386Sopenharmony_ci // In both scenarios we would like to batch as much as possible. 156cb93a386Sopenharmony_ci std::sort(fSortedCmds.begin(), fSortedCmds.end(), 157cb93a386Sopenharmony_ci [](const sk_sp<Cmd>& a, const sk_sp<Cmd>& b) { 158cb93a386Sopenharmony_ci return a->getKey() < b->getKey(); 159cb93a386Sopenharmony_ci }); 160cb93a386Sopenharmony_ci} 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci//------------------------------------------------------------------------------------------------- 163cb93a386Sopenharmony_civoid FakeCanvas::drawShape(ID id, Shape shape, SkIRect r, FakePaint p) { 164cb93a386Sopenharmony_ci SkASSERT(!fFinalized); 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci fDeviceStack.back()->drawShape(id, this->nextPaintersOrder(), shape, r, p); 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_civoid FakeCanvas::clipShape(ID id, Shape shape, SkIRect r) { 170cb93a386Sopenharmony_ci SkASSERT(!fFinalized); 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci fDeviceStack.back()->clipShape(id, this->nextPaintersOrder(), shape, r); 173cb93a386Sopenharmony_ci} 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_civoid FakeCanvas::finalize() { 176cb93a386Sopenharmony_ci SkASSERT(!fFinalized); 177cb93a386Sopenharmony_ci fFinalized = true; 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci for (auto& d : fDeviceStack) { 180cb93a386Sopenharmony_ci d->finalize(); 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci} 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_cistd::vector<ID> FakeCanvas::getOrder() const { 185cb93a386Sopenharmony_ci SkASSERT(fFinalized); 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci std::vector<ID> ops; 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci for (auto& d : fDeviceStack) { 190cb93a386Sopenharmony_ci d->getOrder(&ops); 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci return ops; 194cb93a386Sopenharmony_ci} 195