paint_op_buffer_unittest.cc 159 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "cc/paint/paint_op_buffer.h"
  5. #include <algorithm>
  6. #include "base/bind.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/memory/scoped_refptr.h"
  9. #include "base/strings/stringprintf.h"
  10. #include "base/test/bind.h"
  11. #include "cc/paint/decoded_draw_image.h"
  12. #include "cc/paint/display_item_list.h"
  13. #include "cc/paint/image_provider.h"
  14. #include "cc/paint/image_transfer_cache_entry.h"
  15. #include "cc/paint/paint_flags.h"
  16. #include "cc/paint/paint_image_builder.h"
  17. #include "cc/paint/paint_op_buffer_serializer.h"
  18. #include "cc/paint/paint_op_reader.h"
  19. #include "cc/paint/paint_op_writer.h"
  20. #include "cc/paint/shader_transfer_cache_entry.h"
  21. #include "cc/paint/skottie_resource_metadata.h"
  22. #include "cc/paint/skottie_text_property_value.h"
  23. #include "cc/paint/skottie_wrapper.h"
  24. #include "cc/paint/transfer_cache_entry.h"
  25. #include "cc/test/lottie_test_data.h"
  26. #include "cc/test/paint_op_helper.h"
  27. #include "cc/test/skia_common.h"
  28. #include "cc/test/test_options_provider.h"
  29. #include "cc/test/test_paint_worklet_input.h"
  30. #include "cc/test/test_skcanvas.h"
  31. #include "cc/test/transfer_cache_test_helper.h"
  32. #include "skia/buildflags.h"
  33. #include "testing/gtest/include/gtest/gtest.h"
  34. #include "third_party/skia/include/core/SkColor.h"
  35. #include "third_party/skia/include/core/SkMaskFilter.h"
  36. #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
  37. #include "third_party/skia/include/effects/SkDashPathEffect.h"
  38. #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
  39. #include "third_party/skia/include/private/chromium/SkChromeRemoteGlyphCache.h"
  40. #include "ui/gfx/geometry/test/geometry_util.h"
  41. using testing::_;
  42. using testing::AtLeast;
  43. using testing::Contains;
  44. using testing::Key;
  45. using testing::Mock;
  46. using testing::NiceMock;
  47. using testing::NotNull;
  48. namespace cc {
  49. namespace {
  50. // An arbitrary size guaranteed to fit the size of any serialized op in this
  51. // unit test. This can also be used for deserialized op size safely in this
  52. // unit test suite as generally deserialized ops are smaller.
  53. static constexpr size_t kBufferBytesPerOp = 1000 + sizeof(LargestPaintOp);
  54. template <typename T>
  55. void ValidateOps(PaintOpBuffer* buffer) {
  56. // Make sure all test data is valid before serializing it.
  57. for (auto* op : PaintOpBuffer::Iterator(buffer))
  58. EXPECT_TRUE(static_cast<T*>(op)->IsValid());
  59. }
  60. } // namespace
  61. class PaintOpSerializationTestUtils {
  62. public:
  63. static void FillArbitraryShaderValues(PaintShader* shader, bool use_matrix) {
  64. shader->shader_type_ = PaintShader::Type::kTwoPointConicalGradient;
  65. shader->flags_ = 12345;
  66. shader->end_radius_ = 12.3f;
  67. shader->start_radius_ = 13.4f;
  68. shader->tx_ = SkTileMode::kRepeat;
  69. shader->ty_ = SkTileMode::kMirror;
  70. shader->fallback_color_ = {0.99f, 0.98f, 0.97f, 0.99f};
  71. shader->scaling_behavior_ = PaintShader::ScalingBehavior::kRasterAtScale;
  72. if (use_matrix) {
  73. shader->local_matrix_.emplace(SkMatrix::I());
  74. shader->local_matrix_->setSkewX(10);
  75. shader->local_matrix_->setSkewY(20);
  76. }
  77. shader->center_ = SkPoint::Make(50, 40);
  78. shader->tile_ = SkRect::MakeXYWH(7, 77, 777, 7777);
  79. shader->start_point_ = SkPoint::Make(-1, -5);
  80. shader->end_point_ = SkPoint::Make(13, -13);
  81. shader->start_degrees_ = 123;
  82. shader->end_degrees_ = 456;
  83. // TODO(vmpstr): Add PaintImage/PaintRecord.
  84. shader->colors_ = {{0.1f, 0.2f, 0.3f, 0.4f},
  85. {0.05f, 0.15f, 0.25f, 0.35f},
  86. {0.0f, 0.5f, 0.9f, 0.1f}};
  87. shader->positions_ = {0.f, 0.4f, 1.f};
  88. }
  89. };
  90. TEST(PaintOpBufferTest, Empty) {
  91. PaintOpBuffer buffer;
  92. EXPECT_EQ(buffer.size(), 0u);
  93. EXPECT_EQ(buffer.bytes_used(), sizeof(PaintOpBuffer));
  94. EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
  95. buffer.Reset();
  96. EXPECT_EQ(buffer.size(), 0u);
  97. EXPECT_EQ(buffer.bytes_used(), sizeof(PaintOpBuffer));
  98. EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
  99. PaintOpBuffer buffer2(std::move(buffer));
  100. EXPECT_EQ(buffer.size(), 0u);
  101. EXPECT_EQ(buffer.bytes_used(), sizeof(PaintOpBuffer));
  102. EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
  103. EXPECT_EQ(buffer2.size(), 0u);
  104. EXPECT_EQ(buffer2.bytes_used(), sizeof(PaintOpBuffer));
  105. EXPECT_EQ(PaintOpBuffer::Iterator(&buffer2), false);
  106. }
  107. class PaintOpAppendTest : public ::testing::Test {
  108. public:
  109. PaintOpAppendTest() {
  110. rect_ = SkRect::MakeXYWH(2, 3, 4, 5);
  111. flags_.setColor(SK_ColorMAGENTA);
  112. flags_.setAlpha(100);
  113. }
  114. void PushOps(PaintOpBuffer* buffer) {
  115. buffer->push<SaveLayerOp>(&rect_, &flags_);
  116. buffer->push<SaveOp>();
  117. buffer->push<DrawColorOp>(draw_color_, blend_);
  118. buffer->push<RestoreOp>();
  119. EXPECT_EQ(buffer->size(), 4u);
  120. }
  121. void VerifyOps(PaintOpBuffer* buffer) {
  122. EXPECT_EQ(buffer->size(), 4u);
  123. PaintOpBuffer::Iterator iter(buffer);
  124. ASSERT_EQ(iter->GetType(), PaintOpType::SaveLayer);
  125. SaveLayerOp* save_op = static_cast<SaveLayerOp*>(*iter);
  126. EXPECT_EQ(save_op->bounds, rect_);
  127. EXPECT_EQ(save_op->flags, flags_);
  128. ++iter;
  129. ASSERT_EQ(iter->GetType(), PaintOpType::Save);
  130. ++iter;
  131. ASSERT_EQ(iter->GetType(), PaintOpType::DrawColor);
  132. DrawColorOp* op = static_cast<DrawColorOp*>(*iter);
  133. EXPECT_EQ(op->color, draw_color_);
  134. EXPECT_EQ(op->mode, blend_);
  135. ++iter;
  136. ASSERT_EQ(iter->GetType(), PaintOpType::Restore);
  137. ++iter;
  138. EXPECT_FALSE(iter);
  139. }
  140. private:
  141. SkRect rect_;
  142. PaintFlags flags_;
  143. SkColor4f draw_color_ = SkColors::kRed;
  144. SkBlendMode blend_ = SkBlendMode::kSrc;
  145. };
  146. TEST_F(PaintOpAppendTest, SimpleAppend) {
  147. PaintOpBuffer buffer;
  148. PushOps(&buffer);
  149. VerifyOps(&buffer);
  150. buffer.Reset();
  151. PushOps(&buffer);
  152. VerifyOps(&buffer);
  153. }
  154. TEST_F(PaintOpAppendTest, MoveThenDestruct) {
  155. PaintOpBuffer original;
  156. PushOps(&original);
  157. VerifyOps(&original);
  158. PaintOpBuffer destination(std::move(original));
  159. VerifyOps(&destination);
  160. // Original should be empty, and safe to destruct.
  161. EXPECT_EQ(original.size(), 0u);
  162. EXPECT_EQ(original.bytes_used(), sizeof(PaintOpBuffer));
  163. }
  164. TEST_F(PaintOpAppendTest, MoveThenDestructOperatorEq) {
  165. PaintOpBuffer original;
  166. PushOps(&original);
  167. VerifyOps(&original);
  168. PaintOpBuffer destination;
  169. destination = std::move(original);
  170. VerifyOps(&destination);
  171. // Original should be empty, and safe to destruct.
  172. EXPECT_EQ(original.size(), 0u);
  173. EXPECT_EQ(original.bytes_used(), sizeof(PaintOpBuffer));
  174. EXPECT_EQ(PaintOpBuffer::Iterator(&original), false);
  175. }
  176. TEST_F(PaintOpAppendTest, MoveThenReappend) {
  177. PaintOpBuffer original;
  178. PushOps(&original);
  179. PaintOpBuffer destination(std::move(original));
  180. // Should be possible to reappend to the original and get the same result.
  181. PushOps(&original);
  182. VerifyOps(&original);
  183. EXPECT_EQ(original, destination);
  184. }
  185. TEST_F(PaintOpAppendTest, MoveThenReappendOperatorEq) {
  186. PaintOpBuffer original;
  187. PushOps(&original);
  188. PaintOpBuffer destination;
  189. destination = std::move(original);
  190. // Should be possible to reappend to the original and get the same result.
  191. PushOps(&original);
  192. VerifyOps(&original);
  193. EXPECT_EQ(original, destination);
  194. }
  195. // Verify that a SaveLayerAlpha / Draw / Restore can be optimized to just
  196. // a draw with opacity.
  197. TEST(PaintOpBufferTest, SaveDrawRestore) {
  198. PaintOpBuffer buffer;
  199. float alpha = 0.4f;
  200. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  201. int paint_flags_alpha = 50;
  202. PaintFlags draw_flags;
  203. draw_flags.setColor(SkColors::kMagenta);
  204. draw_flags.setAlpha(paint_flags_alpha);
  205. EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
  206. SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
  207. buffer.push<DrawRectOp>(rect, draw_flags);
  208. buffer.push<RestoreOp>();
  209. SaveCountingCanvas canvas;
  210. buffer.Playback(&canvas);
  211. EXPECT_EQ(0, canvas.save_count_);
  212. EXPECT_EQ(0, canvas.restore_count_);
  213. EXPECT_EQ(rect, canvas.draw_rect_);
  214. // Expect the alpha from the draw and the save layer to be folded together.
  215. // Since alpha is stored in a uint8_t and gets rounded, so use tolerance.
  216. float expected_alpha = alpha * paint_flags_alpha / 255.0f;
  217. EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlphaf()), 0.01f);
  218. }
  219. // Verify that we don't optimize SaveLayerAlpha / DrawTextBlob / Restore.
  220. TEST(PaintOpBufferTest, SaveDrawTextBlobRestore) {
  221. PaintOpBuffer buffer;
  222. float alpha = 0.4f;
  223. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  224. PaintFlags paint_flags;
  225. EXPECT_TRUE(paint_flags.SupportsFoldingAlpha());
  226. buffer.push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()), 0.0f,
  227. 0.0f, paint_flags);
  228. buffer.push<RestoreOp>();
  229. SaveCountingCanvas canvas;
  230. buffer.Playback(&canvas);
  231. EXPECT_EQ(1, canvas.save_count_);
  232. EXPECT_EQ(1, canvas.restore_count_);
  233. }
  234. // The same as SaveDrawRestore, but test that the optimization doesn't apply
  235. // when the drawing op's flags are not compatible with being folded into the
  236. // save layer with opacity.
  237. TEST(PaintOpBufferTest, SaveDrawRestoreFail_BadFlags) {
  238. PaintOpBuffer buffer;
  239. float alpha = 0.4f;
  240. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  241. PaintFlags draw_flags;
  242. draw_flags.setColor(SkColors::kMagenta);
  243. draw_flags.setAlpha(50);
  244. draw_flags.setBlendMode(SkBlendMode::kSrc);
  245. EXPECT_FALSE(draw_flags.SupportsFoldingAlpha());
  246. SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
  247. buffer.push<DrawRectOp>(rect, draw_flags);
  248. buffer.push<RestoreOp>();
  249. SaveCountingCanvas canvas;
  250. buffer.Playback(&canvas);
  251. EXPECT_EQ(1, canvas.save_count_);
  252. EXPECT_EQ(1, canvas.restore_count_);
  253. EXPECT_EQ(rect, canvas.draw_rect_);
  254. EXPECT_EQ(draw_flags.getAlpha(), canvas.paint_.getAlpha());
  255. }
  256. // Same as above, but the save layer itself appears to be a noop.
  257. // See: http://crbug.com/748485. If the inner draw op itself
  258. // doesn't support folding, then the external save can't be skipped.
  259. TEST(PaintOpBufferTest, SaveDrawRestore_BadFlags255Alpha) {
  260. PaintOpBuffer buffer;
  261. float alpha = 1.0f;
  262. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  263. PaintFlags draw_flags;
  264. draw_flags.setColor(SkColors::kMagenta);
  265. draw_flags.setAlpha(50);
  266. draw_flags.setBlendMode(SkBlendMode::kColorBurn);
  267. EXPECT_FALSE(draw_flags.SupportsFoldingAlpha());
  268. SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
  269. buffer.push<DrawRectOp>(rect, draw_flags);
  270. buffer.push<RestoreOp>();
  271. SaveCountingCanvas canvas;
  272. buffer.Playback(&canvas);
  273. EXPECT_EQ(1, canvas.save_count_);
  274. EXPECT_EQ(1, canvas.restore_count_);
  275. EXPECT_EQ(rect, canvas.draw_rect_);
  276. }
  277. // The same as SaveDrawRestore, but test that the optimization doesn't apply
  278. // when there are more than one ops between the save and restore.
  279. TEST(PaintOpBufferTest, SaveDrawRestoreFail_TooManyOps) {
  280. PaintOpBuffer buffer;
  281. float alpha = 0.4f;
  282. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  283. PaintFlags draw_flags;
  284. draw_flags.setColor(SkColors::kMagenta);
  285. draw_flags.setAlpha(50);
  286. draw_flags.setBlendMode(SkBlendMode::kSrcOver);
  287. EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
  288. SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
  289. buffer.push<DrawRectOp>(rect, draw_flags);
  290. buffer.push<NoopOp>();
  291. buffer.push<RestoreOp>();
  292. SaveCountingCanvas canvas;
  293. buffer.Playback(&canvas);
  294. EXPECT_EQ(1, canvas.save_count_);
  295. EXPECT_EQ(1, canvas.restore_count_);
  296. EXPECT_EQ(rect, canvas.draw_rect_);
  297. EXPECT_EQ(draw_flags.getAlpha(), canvas.paint_.getAlpha());
  298. }
  299. // Verify that the save draw restore code works with a single op
  300. // that's not a draw op, and the optimization does not kick in.
  301. TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpNotADrawOp) {
  302. PaintOpBuffer buffer;
  303. float alpha = 0.4f;
  304. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  305. buffer.push<NoopOp>();
  306. buffer.push<RestoreOp>();
  307. SaveCountingCanvas canvas;
  308. buffer.Playback(&canvas);
  309. EXPECT_EQ(1, canvas.save_count_);
  310. EXPECT_EQ(1, canvas.restore_count_);
  311. }
  312. // Test that the save/draw/restore optimization applies if the single op
  313. // is a DrawRecord that itself has a single draw op.
  314. TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleOp) {
  315. sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>();
  316. int paint_flags_alpha = 50;
  317. PaintFlags draw_flags;
  318. draw_flags.setColor(SkColors::kMagenta);
  319. draw_flags.setAlpha(paint_flags_alpha);
  320. EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
  321. SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
  322. record->push<DrawRectOp>(rect, draw_flags);
  323. EXPECT_EQ(record->size(), 1u);
  324. PaintOpBuffer buffer;
  325. float alpha = 0.4f;
  326. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  327. buffer.push<DrawRecordOp>(std::move(record));
  328. buffer.push<RestoreOp>();
  329. SaveCountingCanvas canvas;
  330. buffer.Playback(&canvas);
  331. EXPECT_EQ(0, canvas.save_count_);
  332. EXPECT_EQ(0, canvas.restore_count_);
  333. EXPECT_EQ(rect, canvas.draw_rect_);
  334. float expected_alpha = alpha * paint_flags_alpha / 255.f;
  335. EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlphaf()), 0.01f);
  336. }
  337. // The same as the above SingleOpRecord test, but the single op is not
  338. // a draw op. So, there's no way to fold in the save layer optimization.
  339. // Verify that the optimization doesn't apply and that this doesn't crash.
  340. // See: http://crbug.com/712093.
  341. TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleNonDrawOp) {
  342. sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>();
  343. record->push<NoopOp>();
  344. EXPECT_EQ(record->size(), 1u);
  345. EXPECT_FALSE(record->GetFirstOp()->IsDrawOp());
  346. PaintOpBuffer buffer;
  347. float alpha = 0.4f;
  348. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  349. buffer.push<DrawRecordOp>(std::move(record));
  350. buffer.push<RestoreOp>();
  351. SaveCountingCanvas canvas;
  352. buffer.Playback(&canvas);
  353. EXPECT_EQ(1, canvas.save_count_);
  354. EXPECT_EQ(1, canvas.restore_count_);
  355. }
  356. TEST(PaintOpBufferTest, SaveLayerRestore_DrawColor) {
  357. PaintOpBuffer buffer;
  358. float alpha = 0.4f;
  359. SkColor original = SkColorSetA(50, SK_ColorRED);
  360. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  361. buffer.push<DrawColorOp>(SkColor4f::FromColor(original),
  362. SkBlendMode::kSrcOver);
  363. buffer.push<RestoreOp>();
  364. SaveCountingCanvas canvas;
  365. buffer.Playback(&canvas);
  366. EXPECT_EQ(canvas.save_count_, 0);
  367. EXPECT_EQ(canvas.restore_count_, 0);
  368. uint8_t expected_alpha = SkMulDiv255Round(alpha, SkColorGetA(original));
  369. EXPECT_EQ(canvas.paint_.getColor(), SkColorSetA(original, expected_alpha));
  370. }
  371. TEST(PaintOpBufferTest, DiscardableImagesTracking_EmptyBuffer) {
  372. PaintOpBuffer buffer;
  373. EXPECT_FALSE(buffer.HasDiscardableImages());
  374. }
  375. TEST(PaintOpBufferTest, DiscardableImagesTracking_NoImageOp) {
  376. PaintOpBuffer buffer;
  377. PaintFlags flags;
  378. buffer.push<DrawRectOp>(SkRect::MakeWH(100, 100), flags);
  379. EXPECT_FALSE(buffer.HasDiscardableImages());
  380. }
  381. TEST(PaintOpBufferTest, DiscardableImagesTracking_DrawImage) {
  382. PaintOpBuffer buffer;
  383. PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100));
  384. buffer.push<DrawImageOp>(image, SkIntToScalar(0), SkIntToScalar(0));
  385. EXPECT_TRUE(buffer.HasDiscardableImages());
  386. }
  387. TEST(PaintOpBufferTest, DiscardableImagesTracking_PaintWorkletImage) {
  388. scoped_refptr<TestPaintWorkletInput> input =
  389. base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(32.0f, 32.0f));
  390. PaintOpBuffer buffer;
  391. PaintImage image = CreatePaintWorkletPaintImage(input);
  392. buffer.push<DrawImageOp>(image, SkIntToScalar(0), SkIntToScalar(0));
  393. EXPECT_TRUE(buffer.HasDiscardableImages());
  394. }
  395. TEST(PaintOpBufferTest, DiscardableImagesTracking_PaintWorkletImageRect) {
  396. scoped_refptr<TestPaintWorkletInput> input =
  397. base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(32.0f, 32.0f));
  398. PaintOpBuffer buffer;
  399. PaintImage image = CreatePaintWorkletPaintImage(input);
  400. SkRect src = SkRect::MakeEmpty();
  401. SkRect dst = SkRect::MakeEmpty();
  402. buffer.push<DrawImageRectOp>(image, src, dst,
  403. SkCanvas::kStrict_SrcRectConstraint);
  404. EXPECT_TRUE(buffer.HasDiscardableImages());
  405. }
  406. TEST(PaintOpBufferTest, DiscardableImagesTracking_DrawImageRect) {
  407. PaintOpBuffer buffer;
  408. PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100));
  409. buffer.push<DrawImageRectOp>(image, SkRect::MakeWH(100, 100),
  410. SkRect::MakeWH(100, 100),
  411. SkCanvas::kFast_SrcRectConstraint);
  412. EXPECT_TRUE(buffer.HasDiscardableImages());
  413. }
  414. TEST(PaintOpBufferTest, DiscardableImagesTracking_OpWithFlags) {
  415. PaintOpBuffer buffer;
  416. PaintFlags flags;
  417. auto image = CreateDiscardablePaintImage(gfx::Size(100, 100));
  418. flags.setShader(PaintShader::MakeImage(std::move(image), SkTileMode::kClamp,
  419. SkTileMode::kClamp, nullptr));
  420. buffer.push<DrawRectOp>(SkRect::MakeWH(100, 100), flags);
  421. EXPECT_TRUE(buffer.HasDiscardableImages());
  422. }
  423. TEST(PaintOpBufferTest, SlowPaths) {
  424. auto buffer = sk_make_sp<PaintOpBuffer>();
  425. EXPECT_EQ(buffer->num_slow_paths_up_to_min_for_MSAA(), 0);
  426. // Op without slow paths
  427. PaintFlags noop_flags;
  428. SkRect rect = SkRect::MakeXYWH(2, 3, 4, 5);
  429. buffer->push<SaveLayerOp>(&rect, &noop_flags);
  430. // Line op with a slow path
  431. PaintFlags line_effect_slow;
  432. line_effect_slow.setStrokeWidth(1.f);
  433. line_effect_slow.setStyle(PaintFlags::kStroke_Style);
  434. line_effect_slow.setStrokeCap(PaintFlags::kRound_Cap);
  435. SkScalar intervals[] = {1.f, 1.f};
  436. line_effect_slow.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
  437. buffer->push<DrawLineOp>(1.f, 2.f, 3.f, 4.f, line_effect_slow);
  438. EXPECT_EQ(buffer->num_slow_paths_up_to_min_for_MSAA(), 1);
  439. // Line effect special case that Skia handles specially.
  440. PaintFlags line_effect = line_effect_slow;
  441. line_effect.setStrokeCap(PaintFlags::kButt_Cap);
  442. buffer->push<DrawLineOp>(1.f, 2.f, 3.f, 4.f, line_effect);
  443. EXPECT_EQ(buffer->num_slow_paths_up_to_min_for_MSAA(), 1);
  444. // Antialiased convex path is not slow.
  445. SkPath path;
  446. path.addCircle(2, 2, 5);
  447. EXPECT_TRUE(path.isConvex());
  448. buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, /*antialias=*/true,
  449. UsePaintCache::kDisabled);
  450. EXPECT_EQ(buffer->num_slow_paths_up_to_min_for_MSAA(), 1);
  451. // Concave paths are slow only when antialiased.
  452. SkPath concave = path;
  453. concave.addCircle(3, 4, 2);
  454. EXPECT_FALSE(concave.isConvex());
  455. buffer->push<ClipPathOp>(concave, SkClipOp::kIntersect, /*antialias=*/true,
  456. UsePaintCache::kDisabled);
  457. EXPECT_EQ(buffer->num_slow_paths_up_to_min_for_MSAA(), 2);
  458. buffer->push<ClipPathOp>(concave, SkClipOp::kIntersect, /*antialias=*/false,
  459. UsePaintCache::kDisabled);
  460. EXPECT_EQ(buffer->num_slow_paths_up_to_min_for_MSAA(), 2);
  461. // Drawing a record with slow paths into another adds the same
  462. // number of slow paths as the record.
  463. auto buffer2 = sk_make_sp<PaintOpBuffer>();
  464. EXPECT_EQ(0, buffer2->num_slow_paths_up_to_min_for_MSAA());
  465. buffer2->push<DrawRecordOp>(buffer);
  466. EXPECT_EQ(2, buffer2->num_slow_paths_up_to_min_for_MSAA());
  467. buffer2->push<DrawRecordOp>(buffer);
  468. EXPECT_EQ(4, buffer2->num_slow_paths_up_to_min_for_MSAA());
  469. }
  470. TEST(PaintOpBufferTest, NonAAPaint) {
  471. // PaintOpWithFlags
  472. {
  473. auto buffer = sk_make_sp<PaintOpBuffer>();
  474. EXPECT_FALSE(buffer->HasNonAAPaint());
  475. // Add a PaintOpWithFlags (in this case a line) with AA.
  476. PaintFlags line_effect;
  477. line_effect.setAntiAlias(true);
  478. buffer->push<DrawLineOp>(1.f, 2.f, 3.f, 4.f, line_effect);
  479. EXPECT_FALSE(buffer->HasNonAAPaint());
  480. // Add a PaintOpWithFlags (in this case a line) without AA.
  481. PaintFlags line_effect_no_aa;
  482. line_effect_no_aa.setAntiAlias(false);
  483. buffer->push<DrawLineOp>(1.f, 2.f, 3.f, 4.f, line_effect_no_aa);
  484. EXPECT_TRUE(buffer->HasNonAAPaint());
  485. }
  486. // ClipPathOp
  487. {
  488. auto buffer = sk_make_sp<PaintOpBuffer>();
  489. EXPECT_FALSE(buffer->HasNonAAPaint());
  490. SkPath path;
  491. path.addCircle(2, 2, 5);
  492. // ClipPathOp with AA
  493. buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, /*antialias=*/true,
  494. UsePaintCache::kDisabled);
  495. EXPECT_FALSE(buffer->HasNonAAPaint());
  496. // ClipPathOp without AA
  497. buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, /*antialias=*/false,
  498. UsePaintCache::kDisabled);
  499. EXPECT_TRUE(buffer->HasNonAAPaint());
  500. }
  501. // ClipRRectOp
  502. {
  503. auto buffer = sk_make_sp<PaintOpBuffer>();
  504. EXPECT_FALSE(buffer->HasNonAAPaint());
  505. // ClipRRectOp with AA
  506. buffer->push<ClipRRectOp>(SkRRect::MakeEmpty(), SkClipOp::kIntersect,
  507. true /* antialias */);
  508. EXPECT_FALSE(buffer->HasNonAAPaint());
  509. // ClipRRectOp without AA
  510. buffer->push<ClipRRectOp>(SkRRect::MakeEmpty(), SkClipOp::kIntersect,
  511. false /* antialias */);
  512. EXPECT_TRUE(buffer->HasNonAAPaint());
  513. }
  514. // Drawing a record with non-aa paths into another propogates the value.
  515. {
  516. auto buffer = sk_make_sp<PaintOpBuffer>();
  517. EXPECT_FALSE(buffer->HasNonAAPaint());
  518. auto sub_buffer = sk_make_sp<PaintOpBuffer>();
  519. SkPath path;
  520. path.addCircle(2, 2, 5);
  521. sub_buffer->push<ClipPathOp>(path, SkClipOp::kIntersect,
  522. /*antialias=*/false, UsePaintCache::kDisabled);
  523. EXPECT_TRUE(sub_buffer->HasNonAAPaint());
  524. buffer->push<DrawRecordOp>(sub_buffer);
  525. EXPECT_TRUE(buffer->HasNonAAPaint());
  526. }
  527. // The following PaintOpWithFlags types are overridden to *not* ever have
  528. // non-AA paint. AA is hard to notice, and these kick us out of MSAA in too
  529. // many cases.
  530. // DrawImageOp
  531. {
  532. auto buffer = sk_make_sp<PaintOpBuffer>();
  533. EXPECT_FALSE(buffer->HasNonAAPaint());
  534. PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100));
  535. PaintFlags non_aa_flags;
  536. non_aa_flags.setAntiAlias(true);
  537. buffer->push<DrawImageOp>(image, SkIntToScalar(0), SkIntToScalar(0),
  538. SkSamplingOptions(), &non_aa_flags);
  539. EXPECT_FALSE(buffer->HasNonAAPaint());
  540. }
  541. // DrawIRectOp
  542. {
  543. auto buffer = sk_make_sp<PaintOpBuffer>();
  544. EXPECT_FALSE(buffer->HasNonAAPaint());
  545. PaintFlags non_aa_flags;
  546. non_aa_flags.setAntiAlias(true);
  547. buffer->push<DrawIRectOp>(SkIRect::MakeWH(1, 1), non_aa_flags);
  548. EXPECT_FALSE(buffer->HasNonAAPaint());
  549. }
  550. // SaveLayerOp
  551. {
  552. auto buffer = sk_make_sp<PaintOpBuffer>();
  553. EXPECT_FALSE(buffer->HasNonAAPaint());
  554. PaintFlags non_aa_flags;
  555. non_aa_flags.setAntiAlias(true);
  556. auto bounds = SkRect::MakeWH(1, 1);
  557. buffer->push<SaveLayerOp>(&bounds, &non_aa_flags);
  558. EXPECT_FALSE(buffer->HasNonAAPaint());
  559. }
  560. }
  561. class PaintOpBufferOffsetsTest : public ::testing::Test {
  562. public:
  563. void SetUp() override {}
  564. void TearDown() override {
  565. offsets_.clear();
  566. buffer_.Reset();
  567. }
  568. template <typename T, typename... Args>
  569. void push_op(Args&&... args) {
  570. offsets_.push_back(buffer_.next_op_offset());
  571. buffer_.push<T>(std::forward<Args>(args)...);
  572. }
  573. // Returns a subset of offsets_ by selecting only the specified indices.
  574. std::vector<size_t> Select(const std::vector<size_t>& indices) {
  575. std::vector<size_t> result;
  576. for (size_t i : indices)
  577. result.push_back(offsets_[i]);
  578. return result;
  579. }
  580. void Playback(SkCanvas* canvas, const std::vector<size_t>& offsets) {
  581. buffer_.Playback(canvas, PlaybackParams(nullptr), &offsets);
  582. }
  583. protected:
  584. std::vector<size_t> offsets_;
  585. PaintOpBuffer buffer_;
  586. };
  587. TEST_F(PaintOpBufferOffsetsTest, EmptyClipRectShouldRejectAnOp) {
  588. SkCanvas device(0, 0);
  589. SkCanvas* canvas = &device;
  590. canvas->translate(-254, 0);
  591. SkIRect bounds = canvas->getDeviceClipBounds();
  592. EXPECT_TRUE(bounds.isEmpty());
  593. SkMatrix ctm = canvas->getTotalMatrix();
  594. EXPECT_EQ(ctm[2], -254);
  595. scoped_refptr<TestPaintWorkletInput> input =
  596. base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(32.0f, 32.0f));
  597. PaintImage image = CreatePaintWorkletPaintImage(input);
  598. SkRect src = SkRect::MakeLTRB(0, 0, 100, 100);
  599. SkRect dst = SkRect::MakeLTRB(168, -23, 268, 77);
  600. push_op<DrawImageRectOp>(image, src, dst,
  601. SkCanvas::kStrict_SrcRectConstraint);
  602. std::vector<size_t> offsets = Select({0});
  603. for (PaintOpBuffer::PlaybackFoldingIterator iter(&buffer_, &offsets); iter;
  604. ++iter) {
  605. const PaintOp* op = *iter;
  606. EXPECT_EQ(op->GetType(), PaintOpType::DrawImageRect);
  607. EXPECT_TRUE(PaintOp::QuickRejectDraw(op, canvas));
  608. }
  609. }
  610. TEST_F(PaintOpBufferOffsetsTest, ContiguousIndices) {
  611. testing::StrictMock<MockCanvas> canvas;
  612. push_op<DrawColorOp>(SkColor4f::FromColor(0u), SkBlendMode::kClear);
  613. push_op<DrawColorOp>(SkColor4f::FromColor(1u), SkBlendMode::kClear);
  614. push_op<DrawColorOp>(SkColor4f::FromColor(2u), SkBlendMode::kClear);
  615. push_op<DrawColorOp>(SkColor4f::FromColor(3u), SkBlendMode::kClear);
  616. push_op<DrawColorOp>(SkColor4f::FromColor(4u), SkBlendMode::kClear);
  617. // Plays all items.
  618. testing::Sequence s;
  619. EXPECT_CALL(canvas, OnDrawPaintWithColor(0u)).InSequence(s);
  620. EXPECT_CALL(canvas, OnDrawPaintWithColor(1u)).InSequence(s);
  621. EXPECT_CALL(canvas, OnDrawPaintWithColor(2u)).InSequence(s);
  622. EXPECT_CALL(canvas, OnDrawPaintWithColor(3u)).InSequence(s);
  623. EXPECT_CALL(canvas, OnDrawPaintWithColor(4u)).InSequence(s);
  624. Playback(&canvas, Select({0, 1, 2, 3, 4}));
  625. }
  626. TEST_F(PaintOpBufferOffsetsTest, NonContiguousIndices) {
  627. testing::StrictMock<MockCanvas> canvas;
  628. push_op<DrawColorOp>(SkColor4f::FromColor(0u), SkBlendMode::kClear);
  629. push_op<DrawColorOp>(SkColor4f::FromColor(1u), SkBlendMode::kClear);
  630. push_op<DrawColorOp>(SkColor4f::FromColor(2u), SkBlendMode::kClear);
  631. push_op<DrawColorOp>(SkColor4f::FromColor(3u), SkBlendMode::kClear);
  632. push_op<DrawColorOp>(SkColor4f::FromColor(4u), SkBlendMode::kClear);
  633. // Plays 0, 1, 3, 4 indices.
  634. testing::Sequence s;
  635. EXPECT_CALL(canvas, OnDrawPaintWithColor(0u)).InSequence(s);
  636. EXPECT_CALL(canvas, OnDrawPaintWithColor(1u)).InSequence(s);
  637. EXPECT_CALL(canvas, OnDrawPaintWithColor(3u)).InSequence(s);
  638. EXPECT_CALL(canvas, OnDrawPaintWithColor(4u)).InSequence(s);
  639. Playback(&canvas, Select({0, 1, 3, 4}));
  640. }
  641. TEST_F(PaintOpBufferOffsetsTest, FirstTwoIndices) {
  642. testing::StrictMock<MockCanvas> canvas;
  643. push_op<DrawColorOp>(SkColor4f::FromColor(0u), SkBlendMode::kClear);
  644. push_op<DrawColorOp>(SkColor4f::FromColor(1u), SkBlendMode::kClear);
  645. push_op<DrawColorOp>(SkColor4f::FromColor(2u), SkBlendMode::kClear);
  646. push_op<DrawColorOp>(SkColor4f::FromColor(3u), SkBlendMode::kClear);
  647. push_op<DrawColorOp>(SkColor4f::FromColor(4u), SkBlendMode::kClear);
  648. // Plays first two indices.
  649. testing::Sequence s;
  650. EXPECT_CALL(canvas, OnDrawPaintWithColor(0u)).InSequence(s);
  651. EXPECT_CALL(canvas, OnDrawPaintWithColor(1u)).InSequence(s);
  652. Playback(&canvas, Select({0, 1}));
  653. }
  654. TEST_F(PaintOpBufferOffsetsTest, MiddleIndex) {
  655. testing::StrictMock<MockCanvas> canvas;
  656. push_op<DrawColorOp>(SkColor4f::FromColor(0u), SkBlendMode::kClear);
  657. push_op<DrawColorOp>(SkColor4f::FromColor(1u), SkBlendMode::kClear);
  658. push_op<DrawColorOp>(SkColor4f::FromColor(2u), SkBlendMode::kClear);
  659. push_op<DrawColorOp>(SkColor4f::FromColor(3u), SkBlendMode::kClear);
  660. push_op<DrawColorOp>(SkColor4f::FromColor(4u), SkBlendMode::kClear);
  661. // Plays index 2.
  662. testing::Sequence s;
  663. EXPECT_CALL(canvas, OnDrawPaintWithColor(2u)).InSequence(s);
  664. Playback(&canvas, Select({2}));
  665. }
  666. TEST_F(PaintOpBufferOffsetsTest, LastTwoElements) {
  667. testing::StrictMock<MockCanvas> canvas;
  668. push_op<DrawColorOp>(SkColor4f::FromColor(0u), SkBlendMode::kClear);
  669. push_op<DrawColorOp>(SkColor4f::FromColor(1u), SkBlendMode::kClear);
  670. push_op<DrawColorOp>(SkColor4f::FromColor(2u), SkBlendMode::kClear);
  671. push_op<DrawColorOp>(SkColor4f::FromColor(3u), SkBlendMode::kClear);
  672. push_op<DrawColorOp>(SkColor4f::FromColor(4u), SkBlendMode::kClear);
  673. // Plays last two elements.
  674. testing::Sequence s;
  675. EXPECT_CALL(canvas, OnDrawPaintWithColor(3u)).InSequence(s);
  676. EXPECT_CALL(canvas, OnDrawPaintWithColor(4u)).InSequence(s);
  677. Playback(&canvas, Select({3, 4}));
  678. }
  679. TEST_F(PaintOpBufferOffsetsTest, ContiguousIndicesWithSaveLayerAlphaRestore) {
  680. testing::StrictMock<MockCanvas> canvas;
  681. push_op<DrawColorOp>(SkColor4f::FromColor(0u), SkBlendMode::kClear);
  682. push_op<DrawColorOp>(SkColor4f::FromColor(1u), SkBlendMode::kClear);
  683. float alpha = 0.4f;
  684. push_op<SaveLayerAlphaOp>(nullptr, alpha);
  685. push_op<RestoreOp>();
  686. push_op<DrawColorOp>(SkColor4f::FromColor(2u), SkBlendMode::kClear);
  687. push_op<DrawColorOp>(SkColor4f::FromColor(3u), SkBlendMode::kClear);
  688. push_op<DrawColorOp>(SkColor4f::FromColor(4u), SkBlendMode::kClear);
  689. // Items are {0, 1, save, restore, 2, 3, 4}.
  690. testing::Sequence s;
  691. EXPECT_CALL(canvas, OnDrawPaintWithColor(0u)).InSequence(s);
  692. EXPECT_CALL(canvas, OnDrawPaintWithColor(1u)).InSequence(s);
  693. // The empty SaveLayerAlpha/Restore is dropped.
  694. EXPECT_CALL(canvas, OnDrawPaintWithColor(2u)).InSequence(s);
  695. EXPECT_CALL(canvas, OnDrawPaintWithColor(3u)).InSequence(s);
  696. EXPECT_CALL(canvas, OnDrawPaintWithColor(4u)).InSequence(s);
  697. Playback(&canvas, Select({0, 1, 2, 3, 4, 5, 6}));
  698. Mock::VerifyAndClearExpectations(&canvas);
  699. }
  700. TEST_F(PaintOpBufferOffsetsTest,
  701. NonContiguousIndicesWithSaveLayerAlphaRestore) {
  702. testing::StrictMock<MockCanvas> canvas;
  703. push_op<DrawColorOp>(SkColor4f::FromColor(0u), SkBlendMode::kClear);
  704. push_op<DrawColorOp>(SkColor4f::FromColor(1u), SkBlendMode::kClear);
  705. float alpha = 0.4f;
  706. push_op<SaveLayerAlphaOp>(nullptr, alpha);
  707. push_op<DrawColorOp>(SkColor4f::FromColor(2u), SkBlendMode::kClear);
  708. push_op<DrawColorOp>(SkColor4f::FromColor(3u), SkBlendMode::kClear);
  709. push_op<RestoreOp>();
  710. push_op<DrawColorOp>(SkColor4f::FromColor(4u), SkBlendMode::kClear);
  711. // Items are {0, 1, save, 2, 3, restore, 4}.
  712. // Plays back all indices.
  713. {
  714. testing::Sequence s;
  715. EXPECT_CALL(canvas, OnDrawPaintWithColor(0u)).InSequence(s);
  716. EXPECT_CALL(canvas, OnDrawPaintWithColor(1u)).InSequence(s);
  717. // The SaveLayerAlpha/Restore is not dropped if we draw the middle
  718. // range, as we need them to represent the two draws inside the layer
  719. // correctly.
  720. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  721. EXPECT_CALL(canvas, OnDrawPaintWithColor(2u)).InSequence(s);
  722. EXPECT_CALL(canvas, OnDrawPaintWithColor(3u)).InSequence(s);
  723. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  724. EXPECT_CALL(canvas, OnDrawPaintWithColor(4u)).InSequence(s);
  725. Playback(&canvas, Select({0, 1, 2, 3, 4, 5, 6}));
  726. }
  727. Mock::VerifyAndClearExpectations(&canvas);
  728. // Skips the middle indices.
  729. {
  730. testing::Sequence s;
  731. EXPECT_CALL(canvas, OnDrawPaintWithColor(0u)).InSequence(s);
  732. EXPECT_CALL(canvas, OnDrawPaintWithColor(1u)).InSequence(s);
  733. // The now-empty SaveLayerAlpha/Restore is dropped
  734. EXPECT_CALL(canvas, OnDrawPaintWithColor(4u)).InSequence(s);
  735. Playback(&canvas, Select({0, 1, 2, 5, 6}));
  736. }
  737. Mock::VerifyAndClearExpectations(&canvas);
  738. }
  739. TEST_F(PaintOpBufferOffsetsTest,
  740. ContiguousIndicesWithSaveLayerAlphaDrawRestore) {
  741. testing::StrictMock<MockCanvas> canvas;
  742. auto add_draw_rect = [this](SkColor c) {
  743. PaintFlags flags;
  744. flags.setColor(c);
  745. push_op<DrawRectOp>(SkRect::MakeWH(1, 1), flags);
  746. };
  747. add_draw_rect(0u);
  748. add_draw_rect(1u);
  749. float alpha = 0.4f;
  750. push_op<SaveLayerAlphaOp>(nullptr, alpha);
  751. add_draw_rect(2u);
  752. push_op<RestoreOp>();
  753. add_draw_rect(3u);
  754. add_draw_rect(4u);
  755. // Items are {0, 1, save, 2, restore, 3, 4}.
  756. testing::Sequence s;
  757. EXPECT_CALL(canvas, OnDrawRectWithColor(0u)).InSequence(s);
  758. EXPECT_CALL(canvas, OnDrawRectWithColor(1u)).InSequence(s);
  759. // The empty SaveLayerAlpha/Restore is dropped, the containing
  760. // operation can be drawn with alpha.
  761. EXPECT_CALL(canvas, OnDrawRectWithColor(2u)).InSequence(s);
  762. EXPECT_CALL(canvas, OnDrawRectWithColor(3u)).InSequence(s);
  763. EXPECT_CALL(canvas, OnDrawRectWithColor(4u)).InSequence(s);
  764. Playback(&canvas, Select({0, 1, 2, 3, 4, 5, 6}));
  765. Mock::VerifyAndClearExpectations(&canvas);
  766. }
  767. TEST_F(PaintOpBufferOffsetsTest,
  768. NonContiguousIndicesWithSaveLayerAlphaDrawRestore) {
  769. testing::StrictMock<MockCanvas> canvas;
  770. auto add_draw_rect = [this](SkColor c) {
  771. PaintFlags flags;
  772. flags.setColor(c);
  773. push_op<DrawRectOp>(SkRect::MakeWH(1, 1), flags);
  774. };
  775. add_draw_rect(0u);
  776. add_draw_rect(1u);
  777. float alpha = 0.4f;
  778. push_op<SaveLayerAlphaOp>(nullptr, alpha);
  779. add_draw_rect(2u);
  780. add_draw_rect(3u);
  781. add_draw_rect(4u);
  782. push_op<RestoreOp>();
  783. // Items are are {0, 1, save, 2, 3, 4, restore}.
  784. // If the middle range is played, then the SaveLayerAlpha/Restore
  785. // can't be dropped.
  786. {
  787. testing::Sequence s;
  788. EXPECT_CALL(canvas, OnDrawRectWithColor(0u)).InSequence(s);
  789. EXPECT_CALL(canvas, OnDrawRectWithColor(1u)).InSequence(s);
  790. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  791. EXPECT_CALL(canvas, OnDrawRectWithColor(2u)).InSequence(s);
  792. EXPECT_CALL(canvas, OnDrawRectWithColor(3u)).InSequence(s);
  793. EXPECT_CALL(canvas, OnDrawRectWithColor(4u)).InSequence(s);
  794. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  795. Playback(&canvas, Select({0, 1, 2, 3, 4, 5, 6}));
  796. }
  797. Mock::VerifyAndClearExpectations(&canvas);
  798. // If the middle range is not played, then the SaveLayerAlpha/Restore
  799. // can be dropped.
  800. {
  801. testing::Sequence s;
  802. EXPECT_CALL(canvas, OnDrawRectWithColor(0u)).InSequence(s);
  803. EXPECT_CALL(canvas, OnDrawRectWithColor(1u)).InSequence(s);
  804. EXPECT_CALL(canvas, OnDrawRectWithColor(4u)).InSequence(s);
  805. Playback(&canvas, Select({0, 1, 2, 5, 6}));
  806. }
  807. Mock::VerifyAndClearExpectations(&canvas);
  808. // If the middle range is not played, then the SaveLayerAlpha/Restore
  809. // can be dropped.
  810. {
  811. testing::Sequence s;
  812. EXPECT_CALL(canvas, OnDrawRectWithColor(0u)).InSequence(s);
  813. EXPECT_CALL(canvas, OnDrawRectWithColor(1u)).InSequence(s);
  814. EXPECT_CALL(canvas, OnDrawRectWithColor(2u)).InSequence(s);
  815. Playback(&canvas, Select({0, 1, 2, 3, 6}));
  816. }
  817. }
  818. TEST(PaintOpBufferTest, SaveLayerAlphaDrawRestoreWithBadBlendMode) {
  819. PaintOpBuffer buffer;
  820. testing::StrictMock<MockCanvas> canvas;
  821. auto add_draw_rect = [](PaintOpBuffer* buffer, SkColor c) {
  822. PaintFlags flags;
  823. flags.setColor(c);
  824. // This blend mode prevents the optimization.
  825. flags.setBlendMode(SkBlendMode::kSrc);
  826. buffer->push<DrawRectOp>(SkRect::MakeWH(1, 1), flags);
  827. };
  828. add_draw_rect(&buffer, 0u);
  829. float alpha = 0.4f;
  830. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  831. add_draw_rect(&buffer, 1u);
  832. buffer.push<RestoreOp>();
  833. add_draw_rect(&buffer, 2u);
  834. {
  835. testing::Sequence s;
  836. EXPECT_CALL(canvas, OnDrawRectWithColor(0u)).InSequence(s);
  837. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  838. EXPECT_CALL(canvas, OnDrawRectWithColor(1u)).InSequence(s);
  839. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  840. EXPECT_CALL(canvas, OnDrawRectWithColor(2u)).InSequence(s);
  841. buffer.Playback(&canvas);
  842. }
  843. }
  844. TEST(PaintOpBufferTest, UnmatchedSaveRestoreNoSideEffects) {
  845. PaintOpBuffer buffer;
  846. testing::StrictMock<MockCanvas> canvas;
  847. auto add_draw_rect = [](PaintOpBuffer* buffer, SkColor c) {
  848. PaintFlags flags;
  849. flags.setColor(c);
  850. buffer->push<DrawRectOp>(SkRect::MakeWH(1, 1), flags);
  851. };
  852. // Push 2 saves.
  853. float alpha = 0.4f;
  854. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  855. add_draw_rect(&buffer, 0u);
  856. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  857. add_draw_rect(&buffer, 1u);
  858. add_draw_rect(&buffer, 2u);
  859. // But only 1 restore.
  860. buffer.push<RestoreOp>();
  861. testing::Sequence s;
  862. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  863. EXPECT_CALL(canvas, OnDrawRectWithColor(0u)).InSequence(s);
  864. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  865. EXPECT_CALL(canvas, OnDrawRectWithColor(1u)).InSequence(s);
  866. EXPECT_CALL(canvas, OnDrawRectWithColor(2u)).InSequence(s);
  867. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  868. // We will restore back to the original save count regardless with 2 restores.
  869. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  870. buffer.Playback(&canvas);
  871. }
  872. std::vector<float> test_floats = {0.f,
  873. 1.f,
  874. -1.f,
  875. 2384.981971f,
  876. 0.0001f,
  877. std::numeric_limits<float>::min(),
  878. std::numeric_limits<float>::max(),
  879. std::numeric_limits<float>::infinity()};
  880. std::vector<uint8_t> test_uint8s = {
  881. 0, 255, 128, 10, 45,
  882. };
  883. static SkRect make_largest_skrect() {
  884. const float limit = std::numeric_limits<float>::max();
  885. return {-limit, -limit, limit, limit};
  886. }
  887. static SkIRect make_largest_skirect() {
  888. // we use half the limit, so that the resulting width/height will not
  889. // overflow.
  890. const int32_t limit = std::numeric_limits<int32_t>::max() >> 1;
  891. return {-limit, -limit, limit, limit};
  892. }
  893. std::vector<SkRect> test_rects = {
  894. SkRect::MakeXYWH(1, 2.5, 3, 4), SkRect::MakeXYWH(0, 0, 0, 0),
  895. make_largest_skrect(), SkRect::MakeXYWH(0.5f, 0.5f, 8.2f, 8.2f),
  896. SkRect::MakeXYWH(-1, -1, 0, 0), SkRect::MakeXYWH(-100, -101, -102, -103),
  897. SkRect::MakeXYWH(0, 0, 0, 0), SkRect::MakeXYWH(0, 0, 0, 0),
  898. SkRect::MakeXYWH(0, 0, 0, 0), SkRect::MakeXYWH(0, 0, 0, 0),
  899. SkRect::MakeXYWH(0, 0, 0, 0), SkRect::MakeXYWH(0, 0, 0, 0),
  900. };
  901. std::vector<SkRRect> test_rrects = {
  902. SkRRect::MakeEmpty(), SkRRect::MakeOval(SkRect::MakeXYWH(1, 2, 3, 4)),
  903. SkRRect::MakeRect(SkRect::MakeXYWH(-10, 100, 5, 4)),
  904. [] {
  905. SkRRect rrect = SkRRect::MakeEmpty();
  906. rrect.setNinePatch(SkRect::MakeXYWH(10, 20, 30, 40), 1, 2, 3, 4);
  907. return rrect;
  908. }(),
  909. };
  910. std::vector<SkIRect> test_irects = {
  911. SkIRect::MakeXYWH(1, 2, 3, 4), SkIRect::MakeXYWH(0, 0, 0, 0),
  912. make_largest_skirect(), SkIRect::MakeXYWH(0, 0, 10, 10),
  913. SkIRect::MakeXYWH(-1, -1, 0, 0), SkIRect::MakeXYWH(-100, -101, -102, -103)};
  914. std::vector<uint32_t> test_ids = {0, 1, 56, 0xFFFFFFFF, 0xFFFFFFFE, 0x10001};
  915. std::vector<SkM44> test_matrices = {
  916. SkM44(),
  917. SkM44::Scale(3.91f, 4.31f, 1.0f),
  918. SkM44::Translate(-5.2f, 8.7f, 0.0f),
  919. SkM44(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  920. SkM44(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
  921. };
  922. std::vector<SkPath> test_paths = {
  923. [] {
  924. SkPath path;
  925. path.moveTo(SkIntToScalar(20), SkIntToScalar(20));
  926. path.lineTo(SkIntToScalar(80), SkIntToScalar(20));
  927. path.lineTo(SkIntToScalar(30), SkIntToScalar(30));
  928. path.lineTo(SkIntToScalar(20), SkIntToScalar(80));
  929. return path;
  930. }(),
  931. [] {
  932. SkPath path;
  933. path.addCircle(2, 2, 5);
  934. path.addCircle(3, 4, 2);
  935. path.addArc(SkRect::MakeXYWH(1, 2, 3, 4), 5, 6);
  936. return path;
  937. }(),
  938. SkPath(),
  939. };
  940. std::vector<PaintFlags> test_flags = {
  941. PaintFlags(),
  942. [] {
  943. PaintFlags flags;
  944. flags.setColor(SK_ColorMAGENTA);
  945. flags.setStrokeWidth(4.2f);
  946. flags.setStrokeMiter(5.91f);
  947. flags.setBlendMode(SkBlendMode::kDst);
  948. flags.setStrokeCap(PaintFlags::kSquare_Cap);
  949. flags.setStrokeJoin(PaintFlags::kBevel_Join);
  950. flags.setStyle(PaintFlags::kStroke_Style);
  951. flags.setFilterQuality(PaintFlags::FilterQuality::kMedium);
  952. flags.setShader(PaintShader::MakeColor({0.1f, 0.2f, 0.3f, 0.4f}));
  953. return flags;
  954. }(),
  955. [] {
  956. PaintFlags flags;
  957. flags.setColor(SK_ColorCYAN);
  958. flags.setAlpha(103);
  959. flags.setStrokeWidth(0.32f);
  960. flags.setStrokeMiter(7.98f);
  961. flags.setBlendMode(SkBlendMode::kSrcOut);
  962. flags.setStrokeCap(PaintFlags::kRound_Cap);
  963. flags.setStrokeJoin(PaintFlags::kRound_Join);
  964. flags.setStyle(PaintFlags::kFill_Style);
  965. flags.setFilterQuality(PaintFlags::FilterQuality::kHigh);
  966. SkScalar intervals[] = {1.f, 1.f};
  967. flags.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
  968. flags.setMaskFilter(SkMaskFilter::MakeBlur(
  969. SkBlurStyle::kOuter_SkBlurStyle, 4.3f));
  970. flags.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(
  971. SK_ColorYELLOW, SK_ColorGREEN));
  972. SkLayerDrawLooper::Builder looper_builder;
  973. looper_builder.addLayer();
  974. looper_builder.addLayer(2.3f, 4.5f);
  975. SkLayerDrawLooper::LayerInfo layer_info;
  976. layer_info.fPaintBits |= SkLayerDrawLooper::kMaskFilter_Bit;
  977. layer_info.fColorMode = SkBlendMode::kDst;
  978. layer_info.fOffset.set(-1.f, 5.2f);
  979. looper_builder.addLayer(layer_info);
  980. flags.setLooper(looper_builder.detach());
  981. sk_sp<PaintShader> shader =
  982. PaintShader::MakeColor(SkColors::kTransparent);
  983. PaintOpSerializationTestUtils::FillArbitraryShaderValues(shader.get(),
  984. true);
  985. flags.setShader(std::move(shader));
  986. return flags;
  987. }(),
  988. [] {
  989. PaintFlags flags;
  990. flags.setShader(PaintShader::MakeColor({0.1f, 0.2f, 0.3f, 0.4f}));
  991. return flags;
  992. }(),
  993. [] {
  994. PaintFlags flags;
  995. sk_sp<PaintShader> shader =
  996. PaintShader::MakeColor(SkColors::kTransparent);
  997. PaintOpSerializationTestUtils::FillArbitraryShaderValues(shader.get(),
  998. false);
  999. flags.setShader(std::move(shader));
  1000. return flags;
  1001. }(),
  1002. [] {
  1003. PaintFlags flags;
  1004. SkPoint points[2] = {SkPoint::Make(1, 2), SkPoint::Make(3, 4)};
  1005. SkColor4f colors[3] = {{0.1f, 0.2f, 0.3f, 0.4f},
  1006. {0.4f, 0.3f, 0.2f, 0.1f},
  1007. {0.2f, 0.4f, 0.6f, 0.0f}};
  1008. SkScalar positions[3] = {0.f, 0.3f, 1.f};
  1009. flags.setShader(PaintShader::MakeLinearGradient(points, colors, positions,
  1010. 3, SkTileMode::kMirror));
  1011. return flags;
  1012. }(),
  1013. [] {
  1014. PaintFlags flags;
  1015. SkColor4f colors[3] = {{0.1f, 0.2f, 0.3f, 0.4f},
  1016. {0.4f, 0.3f, 0.2f, 0.1f},
  1017. {0.2f, 0.4f, 0.6f, 0.0f}};
  1018. flags.setShader(PaintShader::MakeSweepGradient(
  1019. 0.2f, -0.8f, colors, nullptr, 3, SkTileMode::kMirror, 10, 20));
  1020. return flags;
  1021. }(),
  1022. PaintFlags(),
  1023. PaintFlags(),
  1024. };
  1025. std::vector<SkColor4f> test_colors = {
  1026. {0, 0, 0, 0}, {1, 1, 1, 1}, {1, 0.04, 1, 0},
  1027. {0, 0.08, 1, 1}, {1, 0, 1, 0.12}, {0.16, 0, 0, 1},
  1028. };
  1029. std::vector<std::string> test_strings = {
  1030. "", "foobar",
  1031. "blarbideeblarasdfaiousydfp234poiausdofiuapsodfjknla;sdfkjasd;f",
  1032. };
  1033. std::vector<std::vector<SkPoint>> test_point_arrays = {
  1034. std::vector<SkPoint>(),
  1035. {SkPoint::Make(1, 2)},
  1036. {SkPoint::Make(1, 2), SkPoint::Make(-5.4f, -3.8f)},
  1037. {SkPoint::Make(0, 0), SkPoint::Make(5, 6), SkPoint::Make(-1, -1),
  1038. SkPoint::Make(9, 9), SkPoint::Make(50, 50), SkPoint::Make(100, 100)},
  1039. };
  1040. // TODO(enne): In practice, probably all paint images need to be uploaded
  1041. // ahead of time and not be bitmaps. These paint images should be fake
  1042. // gpu resource paint images.
  1043. std::vector<PaintImage> test_images = {
  1044. CreateDiscardablePaintImage(gfx::Size(5, 10)),
  1045. CreateDiscardablePaintImage(gfx::Size(1, 1)),
  1046. CreateDiscardablePaintImage(gfx::Size(50, 50)),
  1047. };
  1048. #if BUILDFLAG(SKIA_SUPPORT_SKOTTIE)
  1049. bool kIsSkottieSupported = true;
  1050. #else
  1051. bool kIsSkottieSupported = false;
  1052. #endif
  1053. // Writes as many ops in |buffer| as can fit in |output_size| to |output|.
  1054. // Records the numbers of bytes written for each op.
  1055. class SimpleSerializer {
  1056. public:
  1057. SimpleSerializer(void* output, size_t output_size)
  1058. : current_(static_cast<char*>(output)),
  1059. output_size_(output_size),
  1060. remaining_(output_size) {}
  1061. void Serialize(const PaintOpBuffer& buffer) {
  1062. bytes_written_.resize(buffer.size());
  1063. for (size_t i = 0; i < buffer.size(); ++i)
  1064. bytes_written_[i] = 0;
  1065. size_t op_idx = 0;
  1066. for (const auto* op : PaintOpBuffer::Iterator(&buffer)) {
  1067. size_t bytes_written = op->Serialize(
  1068. current_, remaining_, options_provider_.serialize_options(), nullptr,
  1069. SkM44(), SkM44());
  1070. if (!bytes_written)
  1071. return;
  1072. PaintOp* written = reinterpret_cast<PaintOp*>(current_.get());
  1073. EXPECT_EQ(op->GetType(), written->GetType());
  1074. EXPECT_EQ(bytes_written, written->skip);
  1075. bytes_written_[op_idx] = bytes_written;
  1076. op_idx++;
  1077. current_ += bytes_written;
  1078. remaining_ -= bytes_written;
  1079. // Number of bytes bytes_written must be a multiple of PaintOpAlign
  1080. // unless the buffer is filled entirely.
  1081. if (remaining_ != 0u)
  1082. DCHECK_EQ(0u, bytes_written % PaintOpBuffer::PaintOpAlign);
  1083. }
  1084. }
  1085. const std::vector<size_t>& bytes_written() const { return bytes_written_; }
  1086. size_t TotalBytesWritten() const { return output_size_ - remaining_; }
  1087. TestOptionsProvider* options_provider() { return &options_provider_; }
  1088. private:
  1089. raw_ptr<char> current_ = nullptr;
  1090. size_t output_size_ = 0u;
  1091. size_t remaining_ = 0u;
  1092. std::vector<size_t> bytes_written_;
  1093. TestOptionsProvider options_provider_;
  1094. };
  1095. class DeserializerIterator {
  1096. public:
  1097. DeserializerIterator(const void* input,
  1098. size_t input_size,
  1099. const PaintOp::DeserializeOptions& options)
  1100. : DeserializerIterator(input,
  1101. static_cast<const char*>(input),
  1102. input_size,
  1103. input_size,
  1104. options) {}
  1105. DeserializerIterator(DeserializerIterator&&) = default;
  1106. DeserializerIterator& operator=(DeserializerIterator&&) = default;
  1107. ~DeserializerIterator() { DestroyDeserializedOp(); }
  1108. DeserializerIterator begin() {
  1109. return DeserializerIterator(input_, static_cast<const char*>(input_),
  1110. input_size_, input_size_, options_);
  1111. }
  1112. DeserializerIterator end() {
  1113. return DeserializerIterator(input_,
  1114. static_cast<const char*>(input_) + input_size_,
  1115. input_size_, 0, options_);
  1116. }
  1117. bool operator!=(const DeserializerIterator& other) {
  1118. return input_ != other.input_ || current_ != other.current_ ||
  1119. input_size_ != other.input_size_ || remaining_ != other.remaining_;
  1120. }
  1121. DeserializerIterator& operator++() {
  1122. CHECK_GE(remaining_, last_bytes_read_);
  1123. current_ += last_bytes_read_;
  1124. remaining_ -= last_bytes_read_;
  1125. if (remaining_ > 0)
  1126. CHECK_GE(remaining_, 4u);
  1127. DeserializeCurrentOp();
  1128. return *this;
  1129. }
  1130. operator bool() const { return remaining_ == 0u; }
  1131. const PaintOp* operator->() const { return deserialized_op_; }
  1132. const PaintOp* operator*() const { return deserialized_op_; }
  1133. private:
  1134. DeserializerIterator(const void* input,
  1135. const char* current,
  1136. size_t input_size,
  1137. size_t remaining,
  1138. const PaintOp::DeserializeOptions& options)
  1139. : input_(input),
  1140. current_(current),
  1141. input_size_(input_size),
  1142. remaining_(remaining),
  1143. options_(options) {
  1144. data_.reset(static_cast<char*>(base::AlignedAlloc(
  1145. sizeof(LargestPaintOp), PaintOpBuffer::PaintOpAlign)));
  1146. DeserializeCurrentOp();
  1147. }
  1148. void DestroyDeserializedOp() {
  1149. if (!deserialized_op_)
  1150. return;
  1151. deserialized_op_->DestroyThis();
  1152. deserialized_op_ = nullptr;
  1153. }
  1154. void DeserializeCurrentOp() {
  1155. DestroyDeserializedOp();
  1156. if (!remaining_)
  1157. return;
  1158. deserialized_op_ = PaintOp::Deserialize(current_, remaining_, data_.get(),
  1159. sizeof(LargestPaintOp),
  1160. &last_bytes_read_, options_);
  1161. }
  1162. raw_ptr<const void> input_ = nullptr;
  1163. const char* current_ = nullptr;
  1164. size_t input_size_ = 0u;
  1165. size_t remaining_ = 0u;
  1166. size_t last_bytes_read_ = 0u;
  1167. PaintOp::DeserializeOptions options_;
  1168. std::unique_ptr<char, base::AlignedFreeDeleter> data_;
  1169. raw_ptr<PaintOp> deserialized_op_ = nullptr;
  1170. };
  1171. void PushAnnotateOps(PaintOpBuffer* buffer) {
  1172. buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::URL, test_rects[0],
  1173. SkData::MakeWithCString("thingerdoowhatchamagig"));
  1174. // Deliberately test both null and empty SkData.
  1175. buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::LINK_TO_DESTINATION,
  1176. test_rects[1], nullptr);
  1177. buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::NAMED_DESTINATION,
  1178. test_rects[2], SkData::MakeEmpty());
  1179. ValidateOps<AnnotateOp>(buffer);
  1180. }
  1181. void PushClipPathOps(PaintOpBuffer* buffer) {
  1182. for (size_t i = 0; i < test_paths.size(); ++i) {
  1183. SkClipOp op = i % 3 ? SkClipOp::kDifference : SkClipOp::kIntersect;
  1184. buffer->push<ClipPathOp>(test_paths[i], op, /*antialias=*/!!(i % 2),
  1185. UsePaintCache::kDisabled);
  1186. }
  1187. ValidateOps<ClipPathOp>(buffer);
  1188. }
  1189. void PushClipRectOps(PaintOpBuffer* buffer) {
  1190. for (size_t i = 0; i < test_rects.size(); ++i) {
  1191. SkClipOp op = i % 2 ? SkClipOp::kIntersect : SkClipOp::kDifference;
  1192. bool antialias = !!(i % 3);
  1193. buffer->push<ClipRectOp>(test_rects[i], op, antialias);
  1194. }
  1195. ValidateOps<ClipRectOp>(buffer);
  1196. }
  1197. void PushClipRRectOps(PaintOpBuffer* buffer) {
  1198. for (size_t i = 0; i < test_rrects.size(); ++i) {
  1199. SkClipOp op = i % 2 ? SkClipOp::kIntersect : SkClipOp::kDifference;
  1200. bool antialias = !!(i % 3);
  1201. buffer->push<ClipRRectOp>(test_rrects[i], op, antialias);
  1202. }
  1203. ValidateOps<ClipRRectOp>(buffer);
  1204. }
  1205. void PushConcatOps(PaintOpBuffer* buffer) {
  1206. for (auto& test_matrix : test_matrices)
  1207. buffer->push<ConcatOp>(test_matrix);
  1208. ValidateOps<ConcatOp>(buffer);
  1209. }
  1210. void PushCustomDataOps(PaintOpBuffer* buffer) {
  1211. for (size_t i = 0; i < test_ids.size(); ++i)
  1212. buffer->push<CustomDataOp>(test_ids[i]);
  1213. ValidateOps<CustomDataOp>(buffer);
  1214. }
  1215. void PushDrawColorOps(PaintOpBuffer* buffer) {
  1216. for (size_t i = 0; i < test_colors.size(); ++i) {
  1217. buffer->push<DrawColorOp>(test_colors[i], static_cast<SkBlendMode>(i));
  1218. }
  1219. ValidateOps<DrawColorOp>(buffer);
  1220. }
  1221. void PushDrawDRRectOps(PaintOpBuffer* buffer) {
  1222. size_t len = std::min(test_rrects.size() - 1, test_flags.size());
  1223. for (size_t i = 0; i < len; ++i) {
  1224. buffer->push<DrawDRRectOp>(test_rrects[i], test_rrects[i + 1],
  1225. test_flags[i]);
  1226. }
  1227. ValidateOps<DrawDRRectOp>(buffer);
  1228. }
  1229. void PushDrawImageOps(PaintOpBuffer* buffer) {
  1230. size_t len =
  1231. std::min({test_images.size(), test_flags.size(), test_floats.size() - 1});
  1232. for (size_t i = 0; i < len; ++i) {
  1233. buffer->push<DrawImageOp>(test_images[i], test_floats[i],
  1234. test_floats[i + 1],
  1235. PaintFlags::FilterQualityToSkSamplingOptions(
  1236. test_flags[i].getFilterQuality()),
  1237. &test_flags[i]);
  1238. }
  1239. // Test optional flags
  1240. // TODO(enne): maybe all these optional ops should not be optional.
  1241. buffer->push<DrawImageOp>(test_images[0], test_floats[0], test_floats[1]);
  1242. ValidateOps<DrawImageOp>(buffer);
  1243. }
  1244. void PushDrawImageRectOps(PaintOpBuffer* buffer) {
  1245. size_t len =
  1246. std::min({test_images.size(), test_flags.size(), test_rects.size() - 1});
  1247. for (size_t i = 0; i < len; ++i) {
  1248. SkCanvas::SrcRectConstraint constraint =
  1249. i % 2 ? SkCanvas::kStrict_SrcRectConstraint
  1250. : SkCanvas::kFast_SrcRectConstraint;
  1251. buffer->push<DrawImageRectOp>(test_images[i], test_rects[i],
  1252. test_rects[i + 1],
  1253. PaintFlags::FilterQualityToSkSamplingOptions(
  1254. test_flags[i].getFilterQuality()),
  1255. &test_flags[i], constraint);
  1256. }
  1257. // Test optional flags.
  1258. buffer->push<DrawImageRectOp>(test_images[0], test_rects[0], test_rects[1],
  1259. SkCanvas::kStrict_SrcRectConstraint);
  1260. ValidateOps<DrawImageRectOp>(buffer);
  1261. }
  1262. void PushDrawIRectOps(PaintOpBuffer* buffer) {
  1263. size_t len = std::min(test_irects.size(), test_flags.size());
  1264. for (size_t i = 0; i < len; ++i)
  1265. buffer->push<DrawIRectOp>(test_irects[i], test_flags[i]);
  1266. ValidateOps<DrawIRectOp>(buffer);
  1267. }
  1268. void PushDrawLineOps(PaintOpBuffer* buffer) {
  1269. size_t len = std::min(test_floats.size() - 3, test_flags.size());
  1270. for (size_t i = 0; i < len; ++i) {
  1271. buffer->push<DrawLineOp>(test_floats[i], test_floats[i + 1],
  1272. test_floats[i + 2], test_floats[i + 3],
  1273. test_flags[i]);
  1274. }
  1275. ValidateOps<DrawLineOp>(buffer);
  1276. }
  1277. void PushDrawOvalOps(PaintOpBuffer* buffer) {
  1278. size_t len = std::min(test_paths.size(), test_flags.size());
  1279. for (size_t i = 0; i < len; ++i)
  1280. buffer->push<DrawOvalOp>(test_rects[i], test_flags[i]);
  1281. ValidateOps<DrawOvalOp>(buffer);
  1282. }
  1283. void PushDrawPathOps(PaintOpBuffer* buffer) {
  1284. size_t len = std::min(test_paths.size(), test_flags.size());
  1285. for (size_t i = 0; i < len; ++i)
  1286. buffer->push<DrawPathOp>(test_paths[i], test_flags[i],
  1287. UsePaintCache::kDisabled);
  1288. ValidateOps<DrawPathOp>(buffer);
  1289. }
  1290. void PushDrawRectOps(PaintOpBuffer* buffer) {
  1291. size_t len = std::min(test_rects.size(), test_flags.size());
  1292. for (size_t i = 0; i < len; ++i)
  1293. buffer->push<DrawRectOp>(test_rects[i], test_flags[i]);
  1294. ValidateOps<DrawRectOp>(buffer);
  1295. }
  1296. void PushDrawRRectOps(PaintOpBuffer* buffer) {
  1297. size_t len = std::min(test_rrects.size(), test_flags.size());
  1298. for (size_t i = 0; i < len; ++i)
  1299. buffer->push<DrawRRectOp>(test_rrects[i], test_flags[i]);
  1300. ValidateOps<DrawRRectOp>(buffer);
  1301. }
  1302. SkottieFrameDataMap GetTestImagesForSkottie(SkottieWrapper& skottie,
  1303. const SkRect& skottie_rect,
  1304. PaintFlags::FilterQuality quality,
  1305. float t) {
  1306. SkottieFrameDataMap images;
  1307. skottie.Seek(
  1308. t,
  1309. base::BindLambdaForTesting([&](SkottieResourceIdHash asset_id,
  1310. float t_frame, sk_sp<SkImage>& image_out,
  1311. SkSamplingOptions& sampling_out) {
  1312. SkottieFrameData frame_data;
  1313. frame_data.image = CreateBitmapImage(
  1314. gfx::Size(skottie_rect.width() / 2, skottie_rect.height() / 2));
  1315. frame_data.quality = quality;
  1316. images[asset_id] = std::move(frame_data);
  1317. return SkottieWrapper::FrameDataFetchResult::NO_UPDATE;
  1318. }));
  1319. return images;
  1320. }
  1321. SkottieFrameDataMap GetNullImagesForSkottie(SkottieWrapper& skottie, float t) {
  1322. SkottieFrameDataMap images;
  1323. skottie.Seek(
  1324. t, base::BindLambdaForTesting(
  1325. [&](SkottieResourceIdHash asset_id, float t_frame,
  1326. sk_sp<SkImage>& image_out, SkSamplingOptions& sampling_out) {
  1327. images[asset_id] = SkottieFrameData();
  1328. return SkottieWrapper::FrameDataFetchResult::NO_UPDATE;
  1329. }));
  1330. return images;
  1331. }
  1332. void PushDrawSkottieOps(PaintOpBuffer* buffer) {
  1333. std::vector<scoped_refptr<SkottieWrapper>> test_skotties;
  1334. std::vector<float> test_skottie_floats;
  1335. std::vector<SkRect> test_skottie_rects;
  1336. std::vector<SkottieFrameDataMap> test_skottie_images;
  1337. std::vector<SkottieColorMap> test_skottie_color_maps;
  1338. std::vector<SkottieTextPropertyValueMap> test_skottie_text_maps;
  1339. if (kIsSkottieSupported) {
  1340. test_skotties = {
  1341. CreateSkottie(gfx::Size(10, 20), 4),
  1342. CreateSkottie(gfx::Size(100, 40), 5),
  1343. CreateSkottie(gfx::Size(80, 70), 6),
  1344. CreateSkottieFromString(kLottieDataWith2Assets),
  1345. CreateSkottieFromString(kLottieDataWith2Assets),
  1346. CreateSkottieFromTestDataDir(kLottieDataWith2TextFileName)};
  1347. test_skottie_floats = {0, 0.1f, 1.f, 0.2f, 0.2f, 0.3f};
  1348. test_skottie_rects = {
  1349. SkRect::MakeXYWH(10, 20, 30, 40), SkRect::MakeXYWH(0, 5, 10, 20),
  1350. SkRect::MakeXYWH(6, 0, 3, 50), SkRect::MakeXYWH(10, 10, 100, 100),
  1351. SkRect::MakeXYWH(10, 10, 100, 100), SkRect::MakeXYWH(5, 5, 50, 50)};
  1352. test_skottie_images = {
  1353. SkottieFrameDataMap(),
  1354. SkottieFrameDataMap(),
  1355. SkottieFrameDataMap(),
  1356. GetTestImagesForSkottie(*test_skotties[3], test_skottie_rects[3],
  1357. PaintFlags::FilterQuality::kHigh,
  1358. test_skottie_floats[3]),
  1359. GetNullImagesForSkottie(*test_skotties[4], test_skottie_floats[4]),
  1360. SkottieFrameDataMap()};
  1361. test_skottie_color_maps = {
  1362. {SkottieMapColor("green", SK_ColorGREEN),
  1363. SkottieMapColor("yellow", SK_ColorYELLOW),
  1364. SkottieMapColor("red", SK_ColorRED),
  1365. SkottieMapColor("blue", SK_ColorBLUE)},
  1366. {},
  1367. {SkottieMapColor("green", SK_ColorGREEN)},
  1368. {SkottieMapColor("transparent", SK_ColorTRANSPARENT)},
  1369. {},
  1370. {}};
  1371. test_skottie_text_maps = {
  1372. {},
  1373. {},
  1374. {},
  1375. {},
  1376. {},
  1377. {{HashSkottieResourceId(kLottieDataWith2TextNode1),
  1378. SkottieTextPropertyValue(
  1379. std::string(kLottieDataWith2TextNode1Text.data()),
  1380. kLottieDataWith2TextNode1Box)},
  1381. {HashSkottieResourceId(kLottieDataWith2TextNode2),
  1382. SkottieTextPropertyValue(
  1383. std::string(kLottieDataWith2TextNode2Text.data()),
  1384. kLottieDataWith2TextNode2Box)}}};
  1385. }
  1386. size_t len = std::min(test_skotties.size(), test_flags.size());
  1387. for (size_t i = 0; i < len; i++) {
  1388. buffer->push<DrawSkottieOp>(test_skotties[i], test_skottie_rects[i],
  1389. test_skottie_floats[i], test_skottie_images[i],
  1390. test_skottie_color_maps[i],
  1391. test_skottie_text_maps[i]);
  1392. }
  1393. ValidateOps<DrawSkottieOp>(buffer);
  1394. }
  1395. void PushDrawTextBlobOps(PaintOpBuffer* buffer) {
  1396. static std::vector<std::vector<sk_sp<SkTypeface>>> test_typefaces = {
  1397. [] {
  1398. return std::vector<sk_sp<SkTypeface>>{SkTypeface::MakeDefault()};
  1399. }(),
  1400. [] {
  1401. return std::vector<sk_sp<SkTypeface>>{SkTypeface::MakeDefault(),
  1402. SkTypeface::MakeDefault()};
  1403. }(),
  1404. };
  1405. static std::vector<sk_sp<SkTextBlob>> test_paint_blobs = {
  1406. [] {
  1407. SkFont font;
  1408. font.setTypeface(test_typefaces[0][0]);
  1409. SkTextBlobBuilder builder;
  1410. int glyph_count = 5;
  1411. const auto& run = builder.allocRun(font, glyph_count, 1.2f, 2.3f);
  1412. // allocRun() allocates only the glyph buffer.
  1413. std::fill(run.glyphs, run.glyphs + glyph_count, 0);
  1414. return builder.make();
  1415. }(),
  1416. [] {
  1417. SkFont font;
  1418. font.setTypeface(test_typefaces[1][0]);
  1419. SkTextBlobBuilder builder;
  1420. int glyph_count = 5;
  1421. const auto& run1 = builder.allocRun(font, glyph_count, 1.2f, 2.3f);
  1422. // allocRun() allocates only the glyph buffer.
  1423. std::fill(run1.glyphs, run1.glyphs + glyph_count, 0);
  1424. glyph_count = 16;
  1425. const auto& run2 = builder.allocRunPos(font, glyph_count);
  1426. // allocRun() allocates the glyph buffer, and 2 scalars per glyph for
  1427. // the pos buffer.
  1428. std::fill(run2.glyphs, run2.glyphs + glyph_count, 0);
  1429. std::fill(run2.pos, run2.pos + glyph_count * 2, 0);
  1430. font.setTypeface(test_typefaces[1][1]);
  1431. glyph_count = 8;
  1432. const auto& run3 = builder.allocRunPosH(font, glyph_count, 0);
  1433. // allocRun() allocates the glyph buffer, and 1 scalar per glyph for the
  1434. // pos buffer.
  1435. std::fill(run3.glyphs, run3.glyphs + glyph_count, 0);
  1436. std::fill(run3.pos, run3.pos + glyph_count, 0);
  1437. return builder.make();
  1438. }(),
  1439. };
  1440. size_t len = std::min(
  1441. {test_paint_blobs.size(), test_flags.size(), test_floats.size() - 1});
  1442. for (size_t i = 0; i < len; ++i) {
  1443. buffer->push<DrawTextBlobOp>(test_paint_blobs[i], test_floats[i],
  1444. test_floats[i + 1], test_flags[i]);
  1445. }
  1446. ValidateOps<DrawTextBlobOp>(buffer);
  1447. }
  1448. void PushNoopOps(PaintOpBuffer* buffer) {
  1449. buffer->push<NoopOp>();
  1450. buffer->push<NoopOp>();
  1451. buffer->push<NoopOp>();
  1452. buffer->push<NoopOp>();
  1453. ValidateOps<NoopOp>(buffer);
  1454. }
  1455. void PushRestoreOps(PaintOpBuffer* buffer) {
  1456. buffer->push<RestoreOp>();
  1457. buffer->push<RestoreOp>();
  1458. buffer->push<RestoreOp>();
  1459. buffer->push<RestoreOp>();
  1460. ValidateOps<RestoreOp>(buffer);
  1461. }
  1462. void PushRotateOps(PaintOpBuffer* buffer) {
  1463. for (size_t i = 0; i < test_floats.size(); ++i)
  1464. buffer->push<RotateOp>(test_floats[i]);
  1465. ValidateOps<RotateOp>(buffer);
  1466. }
  1467. void PushSaveOps(PaintOpBuffer* buffer) {
  1468. buffer->push<SaveOp>();
  1469. buffer->push<SaveOp>();
  1470. buffer->push<SaveOp>();
  1471. buffer->push<SaveOp>();
  1472. ValidateOps<SaveOp>(buffer);
  1473. }
  1474. void PushSaveLayerOps(PaintOpBuffer* buffer) {
  1475. size_t len = std::min(test_flags.size(), test_rects.size());
  1476. for (size_t i = 0; i < len; ++i)
  1477. buffer->push<SaveLayerOp>(&test_rects[i], &test_flags[i]);
  1478. // Test combinations of optional args.
  1479. buffer->push<SaveLayerOp>(nullptr, &test_flags[0]);
  1480. buffer->push<SaveLayerOp>(&test_rects[0], nullptr);
  1481. buffer->push<SaveLayerOp>(nullptr, nullptr);
  1482. ValidateOps<SaveLayerOp>(buffer);
  1483. }
  1484. void PushSaveLayerAlphaOps(PaintOpBuffer* buffer) {
  1485. size_t len = std::min(test_floats.size(), test_rects.size());
  1486. for (size_t i = 0; i < len; ++i)
  1487. buffer->push<SaveLayerAlphaOp>(&test_rects[i], test_floats[i]);
  1488. // Test optional args.
  1489. buffer->push<SaveLayerAlphaOp>(nullptr, test_floats[0]);
  1490. ValidateOps<SaveLayerAlphaOp>(buffer);
  1491. }
  1492. void PushScaleOps(PaintOpBuffer* buffer) {
  1493. for (size_t i = 0; i < test_floats.size() - 1; i += 2)
  1494. buffer->push<ScaleOp>(test_floats[i], test_floats[i + 1]);
  1495. ValidateOps<ScaleOp>(buffer);
  1496. }
  1497. void PushSetMatrixOps(PaintOpBuffer* buffer) {
  1498. for (auto& test_matrix : test_matrices)
  1499. buffer->push<SetMatrixOp>(test_matrix);
  1500. ValidateOps<SetMatrixOp>(buffer);
  1501. }
  1502. void PushTranslateOps(PaintOpBuffer* buffer) {
  1503. for (size_t i = 0; i < test_floats.size() - 1; i += 2)
  1504. buffer->push<TranslateOp>(test_floats[i], test_floats[i + 1]);
  1505. ValidateOps<TranslateOp>(buffer);
  1506. }
  1507. void PushSetNodeIdOps(PaintOpBuffer* buffer) {
  1508. for (size_t i = 0; i < test_ids.size(); i++)
  1509. buffer->push<SetNodeIdOp>(static_cast<int>(test_ids[i]));
  1510. ValidateOps<SetNodeIdOp>(buffer);
  1511. }
  1512. class PaintOpSerializationTest : public ::testing::TestWithParam<uint8_t> {
  1513. public:
  1514. PaintOpType GetParamType() const {
  1515. return static_cast<PaintOpType>(GetParam());
  1516. }
  1517. void PushTestOps(PaintOpType type) {
  1518. switch (type) {
  1519. case PaintOpType::Annotate:
  1520. PushAnnotateOps(&buffer_);
  1521. break;
  1522. case PaintOpType::ClipPath:
  1523. PushClipPathOps(&buffer_);
  1524. break;
  1525. case PaintOpType::ClipRect:
  1526. PushClipRectOps(&buffer_);
  1527. break;
  1528. case PaintOpType::ClipRRect:
  1529. PushClipRRectOps(&buffer_);
  1530. break;
  1531. case PaintOpType::Concat:
  1532. PushConcatOps(&buffer_);
  1533. break;
  1534. case PaintOpType::CustomData:
  1535. PushCustomDataOps(&buffer_);
  1536. break;
  1537. case PaintOpType::DrawColor:
  1538. PushDrawColorOps(&buffer_);
  1539. break;
  1540. case PaintOpType::DrawDRRect:
  1541. PushDrawDRRectOps(&buffer_);
  1542. break;
  1543. case PaintOpType::DrawImage:
  1544. PushDrawImageOps(&buffer_);
  1545. break;
  1546. case PaintOpType::DrawImageRect:
  1547. PushDrawImageRectOps(&buffer_);
  1548. break;
  1549. case PaintOpType::DrawIRect:
  1550. PushDrawIRectOps(&buffer_);
  1551. break;
  1552. case PaintOpType::DrawLine:
  1553. PushDrawLineOps(&buffer_);
  1554. break;
  1555. case PaintOpType::DrawOval:
  1556. PushDrawOvalOps(&buffer_);
  1557. break;
  1558. case PaintOpType::DrawPath:
  1559. PushDrawPathOps(&buffer_);
  1560. break;
  1561. case PaintOpType::DrawRecord:
  1562. // Not supported.
  1563. break;
  1564. case PaintOpType::DrawRect:
  1565. PushDrawRectOps(&buffer_);
  1566. break;
  1567. case PaintOpType::DrawRRect:
  1568. PushDrawRRectOps(&buffer_);
  1569. break;
  1570. case PaintOpType::DrawSkottie:
  1571. PushDrawSkottieOps(&buffer_);
  1572. break;
  1573. case PaintOpType::DrawTextBlob:
  1574. // TODO(crbug.com/1321150): fix the test for DrawTextBlobs
  1575. // PushDrawTextBlobOps(&buffer_);
  1576. break;
  1577. case PaintOpType::Noop:
  1578. PushNoopOps(&buffer_);
  1579. break;
  1580. case PaintOpType::Restore:
  1581. PushRestoreOps(&buffer_);
  1582. break;
  1583. case PaintOpType::Rotate:
  1584. PushRotateOps(&buffer_);
  1585. break;
  1586. case PaintOpType::Save:
  1587. PushSaveOps(&buffer_);
  1588. break;
  1589. case PaintOpType::SaveLayer:
  1590. PushSaveLayerOps(&buffer_);
  1591. break;
  1592. case PaintOpType::SaveLayerAlpha:
  1593. PushSaveLayerAlphaOps(&buffer_);
  1594. break;
  1595. case PaintOpType::Scale:
  1596. PushScaleOps(&buffer_);
  1597. break;
  1598. case PaintOpType::SetMatrix:
  1599. PushSetMatrixOps(&buffer_);
  1600. break;
  1601. case PaintOpType::Translate:
  1602. PushTranslateOps(&buffer_);
  1603. break;
  1604. case PaintOpType::SetNodeId:
  1605. PushSetNodeIdOps(&buffer_);
  1606. break;
  1607. }
  1608. }
  1609. void ResizeOutputBuffer() {
  1610. // An arbitrary deserialization buffer size that should fit all the ops
  1611. // in the buffer_.
  1612. output_size_ = kBufferBytesPerOp * buffer_.size();
  1613. output_.reset(static_cast<char*>(
  1614. base::AlignedAlloc(output_size_, PaintOpBuffer::PaintOpAlign)));
  1615. }
  1616. bool IsTypeSupported() {
  1617. // TODO(crbug.com/1321150): fix the test for DrawTextBlobs
  1618. if (GetParamType() == PaintOpType::DrawTextBlob)
  1619. return false;
  1620. // DrawRecordOps must be flattened and are not currently serialized. All
  1621. // other types must push non-zero amounts of ops in PushTestOps.
  1622. return GetParamType() != PaintOpType::DrawRecord &&
  1623. (GetParamType() != PaintOpType::DrawSkottie || kIsSkottieSupported);
  1624. }
  1625. protected:
  1626. std::unique_ptr<char, base::AlignedFreeDeleter> output_;
  1627. size_t output_size_ = 0u;
  1628. PaintOpBuffer buffer_;
  1629. };
  1630. INSTANTIATE_TEST_SUITE_P(
  1631. P,
  1632. PaintOpSerializationTest,
  1633. ::testing::Range(static_cast<uint8_t>(0),
  1634. static_cast<uint8_t>(PaintOpType::LastPaintOpType)));
  1635. // Test serializing and then deserializing all test ops. They should all
  1636. // write successfully and be identical to the original ops in the buffer.
  1637. TEST_P(PaintOpSerializationTest, SmokeTest) {
  1638. if (!IsTypeSupported())
  1639. return;
  1640. PushTestOps(GetParamType());
  1641. ResizeOutputBuffer();
  1642. SimpleSerializer serializer(output_.get(), output_size_);
  1643. auto canvas =
  1644. serializer.options_provider()->strike_server()->makeAnalysisCanvas(
  1645. 1024, 768, {}, nullptr, true);
  1646. PlaybackParams params(nullptr, canvas->getLocalToDevice());
  1647. params.is_analyzing = true;
  1648. buffer_.Playback(canvas.get(), params);
  1649. std::vector<uint8_t> strike_data;
  1650. serializer.options_provider()->strike_server()->writeStrikeData(&strike_data);
  1651. if (!strike_data.empty()) {
  1652. serializer.options_provider()->strike_client()->readStrikeData(
  1653. strike_data.data(), strike_data.size());
  1654. }
  1655. serializer.Serialize(buffer_);
  1656. // Expect all ops to write more than 0 bytes.
  1657. for (size_t i = 0; i < buffer_.size(); ++i) {
  1658. SCOPED_TRACE(base::StringPrintf(
  1659. "%s #%zd", PaintOpTypeToString(GetParamType()).c_str(), i));
  1660. EXPECT_GT(serializer.bytes_written()[i], 0u);
  1661. }
  1662. PaintOpBuffer::Iterator iter(&buffer_);
  1663. size_t i = 0;
  1664. for (auto* base_written : DeserializerIterator(
  1665. output_.get(), serializer.TotalBytesWritten(),
  1666. serializer.options_provider()->deserialize_options())) {
  1667. SCOPED_TRACE(base::StringPrintf(
  1668. "%s #%zu", PaintOpTypeToString(GetParamType()).c_str(), i));
  1669. ASSERT_EQ(!*iter, !base_written);
  1670. EXPECT_EQ(**iter, *base_written);
  1671. ++iter;
  1672. ++i;
  1673. }
  1674. EXPECT_EQ(buffer_.size(), i);
  1675. }
  1676. // Verify for all test ops that serializing into a smaller size aborts
  1677. // correctly and doesn't write anything.
  1678. TEST_P(PaintOpSerializationTest, SerializationFailures) {
  1679. if (!IsTypeSupported())
  1680. return;
  1681. PushTestOps(GetParamType());
  1682. ResizeOutputBuffer();
  1683. SimpleSerializer serializer(output_.get(), output_size_);
  1684. serializer.Serialize(buffer_);
  1685. std::vector<size_t> bytes_written = serializer.bytes_written();
  1686. TestOptionsProvider options_provider;
  1687. size_t op_idx = 0;
  1688. for (PaintOpBuffer::Iterator iter(&buffer_); iter; ++iter, ++op_idx) {
  1689. SCOPED_TRACE(base::StringPrintf(
  1690. "%s #%zu", PaintOpTypeToString(GetParamType()).c_str(), op_idx));
  1691. size_t expected_bytes = bytes_written[op_idx];
  1692. EXPECT_GT(expected_bytes, 0u);
  1693. EXPECT_EQ(expected_bytes,
  1694. base::bits::AlignUp(expected_bytes, PaintOpWriter::Alignment()));
  1695. // Attempt to write op into a buffer of size |i|, and only expect
  1696. // it to succeed if the buffer is large enough.
  1697. for (size_t i = 0; i < bytes_written[op_idx] + 2; ++i) {
  1698. options_provider.ClearPaintCache();
  1699. options_provider.ForcePurgeSkottieSerializationHistory();
  1700. size_t written_bytes = iter->Serialize(
  1701. output_.get(), i, options_provider.serialize_options(), nullptr,
  1702. SkM44(), SkM44());
  1703. if (i >= expected_bytes) {
  1704. EXPECT_EQ(expected_bytes, written_bytes) << "i: " << i;
  1705. } else {
  1706. EXPECT_EQ(0u, written_bytes) << "i: " << i;
  1707. }
  1708. }
  1709. }
  1710. }
  1711. // Verify that deserializing test ops from too small buffers aborts
  1712. // correctly, in case the deserialized data is lying about how big it is.
  1713. TEST_P(PaintOpSerializationTest, DeserializationFailures) {
  1714. if (!IsTypeSupported())
  1715. return;
  1716. PushTestOps(GetParamType());
  1717. ResizeOutputBuffer();
  1718. SimpleSerializer serializer(output_.get(), output_size_);
  1719. serializer.Serialize(buffer_);
  1720. TestOptionsProvider* options_provider = serializer.options_provider();
  1721. char* first = static_cast<char*>(output_.get());
  1722. char* current = first;
  1723. static constexpr size_t kAlign = PaintOpBuffer::PaintOpAlign;
  1724. static constexpr size_t kOutputOpSize = kBufferBytesPerOp;
  1725. std::unique_ptr<char, base::AlignedFreeDeleter> deserialize_buffer_(
  1726. static_cast<char*>(base::AlignedAlloc(kOutputOpSize, kAlign)));
  1727. size_t op_idx = 0;
  1728. size_t total_read = 0;
  1729. for (PaintOpBuffer::Iterator iter(&buffer_); iter; ++iter, ++op_idx) {
  1730. PaintOp* serialized = reinterpret_cast<PaintOp*>(current);
  1731. uint32_t skip = serialized->skip;
  1732. // Read from buffers of various sizes to make sure that having a serialized
  1733. // op size that is larger than the input buffer provided causes a
  1734. // deserialization failure to return nullptr. Also test a few valid sizes
  1735. // larger than read size.
  1736. for (size_t read_size = 0; read_size < skip + kAlign * 2 + 2; ++read_size) {
  1737. SCOPED_TRACE(
  1738. base::StringPrintf("%s #%zd, read_size: %zu, align: %zu, skip: %u",
  1739. PaintOpTypeToString(GetParamType()).c_str(),
  1740. op_idx, read_size, kAlign, skip));
  1741. // Because PaintOp::Deserialize early outs when the input size is < skip
  1742. // deliberately lie about the skip. This op tooooootally fits.
  1743. // This will verify that individual op deserializing code behaves
  1744. // properly when presented with invalid offsets.
  1745. serialized->skip = read_size;
  1746. size_t bytes_read = 0;
  1747. PaintOp* written = PaintOp::Deserialize(
  1748. current, read_size, deserialize_buffer_.get(), kOutputOpSize,
  1749. &bytes_read, options_provider->deserialize_options());
  1750. // Deserialize buffers with valid ops until the last op. This verifies
  1751. // that the complete buffer is invalidated on encountering the first
  1752. // corrupted op.
  1753. auto deserialized_buffer = PaintOpBuffer::MakeFromMemory(
  1754. first, total_read + read_size,
  1755. options_provider->deserialize_options());
  1756. // Skips are only valid if they are aligned.
  1757. if (read_size >= skip && read_size % kAlign == 0) {
  1758. ASSERT_NE(nullptr, written);
  1759. ASSERT_LE(written->skip, kOutputOpSize);
  1760. EXPECT_EQ(GetParamType(), written->GetType());
  1761. EXPECT_EQ(serialized->skip, bytes_read);
  1762. ASSERT_NE(nullptr, deserialized_buffer);
  1763. EXPECT_EQ(deserialized_buffer->size(), op_idx + 1);
  1764. } else if (read_size == 0 && op_idx != 0) {
  1765. // If no data was read for a subsequent op while some ops were
  1766. // deserialized, we still have a valid buffer with the deserialized ops.
  1767. ASSERT_NE(nullptr, deserialized_buffer);
  1768. EXPECT_EQ(deserialized_buffer->size(), op_idx);
  1769. } else {
  1770. // If a subsequent op was corrupted or no ops could be serialized, we
  1771. // have an invalid buffer.
  1772. EXPECT_EQ(nullptr, written);
  1773. // If the buffer is exactly 0 bytes, then MakeFromMemory treats it as a
  1774. // valid empty buffer.
  1775. if (deserialized_buffer) {
  1776. EXPECT_EQ(0u, read_size);
  1777. EXPECT_EQ(0u, deserialized_buffer->size());
  1778. // Verify that we can create an iterator from this buffer, but it's
  1779. // empty.
  1780. PaintOpBuffer::Iterator it(deserialized_buffer.get());
  1781. EXPECT_FALSE(it);
  1782. } else {
  1783. EXPECT_NE(0u, read_size);
  1784. EXPECT_EQ(nullptr, deserialized_buffer.get());
  1785. }
  1786. }
  1787. if (written)
  1788. written->DestroyThis();
  1789. }
  1790. serialized->skip = skip;
  1791. current += skip;
  1792. total_read += skip;
  1793. }
  1794. }
  1795. TEST_P(PaintOpSerializationTest, UsesOverridenFlags) {
  1796. if (!PaintOp::TypeHasFlags(GetParamType()))
  1797. return;
  1798. // TODO(crbug.com/1321150): fix the test for DrawTextBlobs
  1799. if (GetParamType() == PaintOpType::DrawTextBlob)
  1800. return;
  1801. PushTestOps(GetParamType());
  1802. ResizeOutputBuffer();
  1803. TestOptionsProvider options_provider;
  1804. size_t deserialized_size = sizeof(LargestPaintOp) + PaintOp::kMaxSkip;
  1805. std::unique_ptr<char, base::AlignedFreeDeleter> deserialized(
  1806. static_cast<char*>(
  1807. base::AlignedAlloc(deserialized_size, PaintOpBuffer::PaintOpAlign)));
  1808. for (const auto* op : PaintOpBuffer::Iterator(&buffer_)) {
  1809. size_t bytes_written = op->Serialize(output_.get(), output_size_,
  1810. options_provider.serialize_options(),
  1811. nullptr, SkM44(), SkM44());
  1812. size_t bytes_read = 0u;
  1813. PaintOp* written = PaintOp::Deserialize(
  1814. output_.get(), bytes_written, deserialized.get(), deserialized_size,
  1815. &bytes_read, options_provider.deserialize_options());
  1816. ASSERT_TRUE(written) << PaintOpTypeToString(GetParamType());
  1817. EXPECT_EQ(*op, *written);
  1818. written->DestroyThis();
  1819. written = nullptr;
  1820. PaintFlags override_flags = static_cast<const PaintOpWithFlags*>(op)->flags;
  1821. override_flags.setAlpha(override_flags.getAlpha() * 0.5);
  1822. bytes_written = op->Serialize(output_.get(), output_size_,
  1823. options_provider.serialize_options(),
  1824. &override_flags, SkM44(), SkM44());
  1825. written = PaintOp::Deserialize(
  1826. output_.get(), bytes_written, deserialized.get(), deserialized_size,
  1827. &bytes_read, options_provider.deserialize_options());
  1828. ASSERT_TRUE(written);
  1829. ASSERT_TRUE(written->IsPaintOpWithFlags());
  1830. EXPECT_EQ(static_cast<const PaintOpWithFlags*>(written)->flags.getAlpha(),
  1831. override_flags.getAlpha());
  1832. written->DestroyThis();
  1833. written = nullptr;
  1834. }
  1835. }
  1836. TEST(PaintOpSerializationTest, CompleteBufferSerialization) {
  1837. PaintOpBuffer buffer;
  1838. PushDrawIRectOps(&buffer);
  1839. PaintOpBufferSerializer::Preamble preamble;
  1840. preamble.content_size = gfx::Size(1000, 1000);
  1841. preamble.playback_rect = gfx::Rect(preamble.content_size);
  1842. preamble.full_raster_rect = preamble.playback_rect;
  1843. preamble.requires_clear = true;
  1844. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  1845. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  1846. PaintOpBuffer::PaintOpAlign)));
  1847. TestOptionsProvider options_provider;
  1848. SimpleBufferSerializer serializer(memory.get(),
  1849. PaintOpBuffer::kInitialBufferSize,
  1850. options_provider.serialize_options());
  1851. serializer.Serialize(&buffer, nullptr, preamble);
  1852. ASSERT_NE(serializer.written(), 0u);
  1853. auto deserialized_buffer =
  1854. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  1855. options_provider.deserialize_options());
  1856. ASSERT_TRUE(deserialized_buffer);
  1857. // The deserialized buffer has an extra pair of save/restores and a clear, for
  1858. // the preamble and root buffer.
  1859. ASSERT_EQ(deserialized_buffer->size(), buffer.size() + 4u);
  1860. size_t i = 0;
  1861. auto serialized_iter = PaintOpBuffer::Iterator(&buffer);
  1862. for (const auto* op : PaintOpBuffer::Iterator(deserialized_buffer.get())) {
  1863. SCOPED_TRACE(i);
  1864. i++;
  1865. if (i == 1) {
  1866. // Save.
  1867. ASSERT_EQ(op->GetType(), PaintOpType::Save)
  1868. << PaintOpTypeToString(op->GetType());
  1869. continue;
  1870. }
  1871. if (i == 2) {
  1872. // Preamble partial raster clear.
  1873. ASSERT_EQ(op->GetType(), PaintOpType::DrawColor)
  1874. << PaintOpTypeToString(op->GetType());
  1875. continue;
  1876. }
  1877. if (i == 3) {
  1878. // Preamble playback rect clip.
  1879. ASSERT_EQ(op->GetType(), PaintOpType::ClipRect)
  1880. << PaintOpTypeToString(op->GetType());
  1881. EXPECT_EQ(static_cast<const ClipRectOp*>(op)->rect,
  1882. gfx::RectToSkRect(preamble.playback_rect));
  1883. continue;
  1884. }
  1885. if (serialized_iter) {
  1886. // Root buffer.
  1887. ASSERT_EQ(op->GetType(), (*serialized_iter)->GetType())
  1888. << PaintOpTypeToString(op->GetType());
  1889. EXPECT_EQ(*op, **serialized_iter);
  1890. ++serialized_iter;
  1891. continue;
  1892. }
  1893. // End restore.
  1894. ASSERT_EQ(op->GetType(), PaintOpType::Restore)
  1895. << PaintOpTypeToString(op->GetType());
  1896. }
  1897. }
  1898. TEST(PaintOpSerializationTest, DoNotPreservePaintOps) {
  1899. PaintOpBuffer buffer;
  1900. PushDrawIRectOps(&buffer);
  1901. PaintOpBufferSerializer::Preamble preamble;
  1902. preamble.content_size = gfx::Size(1000, 1000);
  1903. preamble.playback_rect = gfx::Rect(preamble.content_size);
  1904. preamble.full_raster_rect = preamble.playback_rect;
  1905. preamble.requires_clear = true;
  1906. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  1907. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  1908. PaintOpBuffer::PaintOpAlign)));
  1909. TestOptionsProvider options_provider;
  1910. SimpleBufferSerializer serializer(memory.get(),
  1911. PaintOpBuffer::kInitialBufferSize,
  1912. options_provider.serialize_options());
  1913. serializer.SerializeAndDestroy(&buffer, nullptr, preamble);
  1914. ASSERT_NE(serializer.written(), 0u);
  1915. EXPECT_TRUE(buffer.are_ops_destroyed());
  1916. }
  1917. TEST(PaintOpSerializationTest, Preamble) {
  1918. PaintOpBufferSerializer::Preamble preamble;
  1919. preamble.content_size = gfx::Size(30, 40);
  1920. preamble.full_raster_rect = gfx::Rect(10, 20, 8, 7);
  1921. preamble.playback_rect = gfx::Rect(12, 25, 1, 2);
  1922. preamble.post_translation = gfx::Vector2dF(4.3f, 7.f);
  1923. preamble.post_scale = gfx::Vector2dF(0.5f, 0.5f);
  1924. preamble.requires_clear = true;
  1925. PaintOpBuffer buffer;
  1926. buffer.push<DrawColorOp>(SkColors::kBlue, SkBlendMode::kSrc);
  1927. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  1928. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  1929. PaintOpBuffer::PaintOpAlign)));
  1930. TestOptionsProvider options_provider;
  1931. SimpleBufferSerializer serializer(memory.get(),
  1932. PaintOpBuffer::kInitialBufferSize,
  1933. options_provider.serialize_options());
  1934. serializer.SerializeAndDestroy(&buffer, nullptr, preamble);
  1935. ASSERT_NE(serializer.written(), 0u);
  1936. auto deserialized_buffer =
  1937. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  1938. options_provider.deserialize_options());
  1939. ASSERT_TRUE(deserialized_buffer);
  1940. // 5 ops for the preamble and 2 for save/restore.
  1941. ASSERT_EQ(deserialized_buffer->size(), buffer.size() + 7u);
  1942. size_t i = 0;
  1943. for (const auto* op : PaintOpBuffer::Iterator(deserialized_buffer.get())) {
  1944. i++;
  1945. if (i == 1) {
  1946. // Save.
  1947. ASSERT_EQ(op->GetType(), PaintOpType::Save)
  1948. << PaintOpTypeToString(op->GetType());
  1949. continue;
  1950. }
  1951. if (i == 2) {
  1952. // Translate.
  1953. ASSERT_EQ(op->GetType(), PaintOpType::Translate)
  1954. << PaintOpTypeToString(op->GetType());
  1955. const auto* translate_op = static_cast<const TranslateOp*>(op);
  1956. EXPECT_EQ(translate_op->dx, -preamble.full_raster_rect.x());
  1957. EXPECT_EQ(translate_op->dy, -preamble.full_raster_rect.y());
  1958. continue;
  1959. }
  1960. if (i == 3) {
  1961. // Clip.
  1962. ASSERT_EQ(op->GetType(), PaintOpType::ClipRect)
  1963. << PaintOpTypeToString(op->GetType());
  1964. const auto* clip_op = static_cast<const ClipRectOp*>(op);
  1965. EXPECT_RECTF_EQ(gfx::SkRectToRectF(clip_op->rect),
  1966. gfx::RectF(preamble.playback_rect));
  1967. continue;
  1968. }
  1969. if (i == 4) {
  1970. // Post translate.
  1971. ASSERT_EQ(op->GetType(), PaintOpType::Translate)
  1972. << PaintOpTypeToString(op->GetType());
  1973. const auto* translate_op = static_cast<const TranslateOp*>(op);
  1974. EXPECT_EQ(translate_op->dx, preamble.post_translation.x());
  1975. EXPECT_EQ(translate_op->dy, preamble.post_translation.y());
  1976. continue;
  1977. }
  1978. if (i == 5) {
  1979. // Scale.
  1980. ASSERT_EQ(op->GetType(), PaintOpType::Scale)
  1981. << PaintOpTypeToString(op->GetType());
  1982. const auto* scale_op = static_cast<const ScaleOp*>(op);
  1983. EXPECT_EQ(scale_op->sx, preamble.post_scale.x());
  1984. EXPECT_EQ(scale_op->sy, preamble.post_scale.y());
  1985. continue;
  1986. }
  1987. if (i == 6) {
  1988. // Partial raster clear goes last.
  1989. ASSERT_EQ(op->GetType(), PaintOpType::DrawColor)
  1990. << PaintOpTypeToString(op->GetType());
  1991. const auto* draw_color_op = static_cast<const DrawColorOp*>(op);
  1992. EXPECT_EQ(draw_color_op->color, SkColors::kTransparent);
  1993. EXPECT_EQ(draw_color_op->mode, SkBlendMode::kSrc);
  1994. continue;
  1995. }
  1996. if (i == 7) {
  1997. // Buffer.
  1998. EXPECT_EQ(*op, *buffer.GetFirstOp());
  1999. continue;
  2000. }
  2001. // End restore.
  2002. ASSERT_EQ(op->GetType(), PaintOpType::Restore)
  2003. << PaintOpTypeToString(op->GetType());
  2004. }
  2005. }
  2006. TEST(PaintOpSerializationTest, SerializesNestedRecords) {
  2007. auto record = sk_make_sp<PaintOpBuffer>();
  2008. record->push<ScaleOp>(0.5f, 0.75f);
  2009. record->push<DrawRectOp>(SkRect::MakeWH(10.f, 20.f), PaintFlags());
  2010. PaintOpBuffer buffer;
  2011. buffer.push<DrawRecordOp>(record);
  2012. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  2013. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  2014. PaintOpBuffer::PaintOpAlign)));
  2015. TestOptionsProvider options_provider;
  2016. SimpleBufferSerializer serializer(memory.get(),
  2017. PaintOpBuffer::kInitialBufferSize,
  2018. options_provider.serialize_options());
  2019. PaintOpBufferSerializer::Preamble preamble;
  2020. serializer.Serialize(&buffer, nullptr, preamble);
  2021. ASSERT_NE(serializer.written(), 0u);
  2022. auto deserialized_buffer =
  2023. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  2024. options_provider.deserialize_options());
  2025. ASSERT_TRUE(deserialized_buffer);
  2026. ASSERT_EQ(deserialized_buffer->size(), record->size() + 5u);
  2027. size_t i = 0;
  2028. auto serialized_iter = PaintOpBuffer::Iterator(record.get());
  2029. for (const auto* op : PaintOpBuffer::Iterator(deserialized_buffer.get())) {
  2030. i++;
  2031. if (i == 1 || i == 3) {
  2032. // First 2 saves.
  2033. ASSERT_EQ(op->GetType(), PaintOpType::Save)
  2034. << PaintOpTypeToString(op->GetType());
  2035. continue;
  2036. }
  2037. // Clear.
  2038. if (i == 2) {
  2039. ASSERT_EQ(op->GetType(), PaintOpType::DrawColor)
  2040. << PaintOpTypeToString(op->GetType());
  2041. continue;
  2042. }
  2043. if (serialized_iter) {
  2044. // Nested buffer.
  2045. ASSERT_EQ(op->GetType(), (*serialized_iter)->GetType())
  2046. << PaintOpTypeToString(op->GetType());
  2047. EXPECT_EQ(*op, **serialized_iter);
  2048. ++serialized_iter;
  2049. continue;
  2050. }
  2051. // End restores.
  2052. ASSERT_EQ(op->GetType(), PaintOpType::Restore)
  2053. << PaintOpTypeToString(op->GetType());
  2054. }
  2055. }
  2056. TEST(PaintOpBufferTest, ClipsImagesDuringSerialization) {
  2057. struct {
  2058. gfx::Rect clip_rect;
  2059. gfx::Rect image_rect;
  2060. bool should_draw;
  2061. } test_cases[] = {
  2062. {gfx::Rect(0, 0, 100, 100), gfx::Rect(50, 50, 100, 100), true},
  2063. {gfx::Rect(0, 0, 100, 100), gfx::Rect(105, 105, 100, 100), false},
  2064. {gfx::Rect(0, 0, 500, 500), gfx::Rect(450, 450, 100, 100), true},
  2065. {gfx::Rect(0, 0, 500, 500), gfx::Rect(750, 750, 100, 100), false},
  2066. {gfx::Rect(250, 250, 250, 250), gfx::Rect(450, 450, 100, 100), true},
  2067. {gfx::Rect(250, 250, 250, 250), gfx::Rect(50, 50, 100, 100), false},
  2068. {gfx::Rect(0, 0, 100, 500), gfx::Rect(250, 250, 100, 100), false},
  2069. {gfx::Rect(0, 0, 200, 500), gfx::Rect(100, 250, 100, 100), true}};
  2070. for (const auto& test_case : test_cases) {
  2071. PaintOpBuffer buffer;
  2072. buffer.push<DrawImageOp>(
  2073. CreateDiscardablePaintImage(test_case.image_rect.size()),
  2074. static_cast<SkScalar>(test_case.image_rect.x()),
  2075. static_cast<SkScalar>(test_case.image_rect.y()));
  2076. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  2077. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  2078. PaintOpBuffer::PaintOpAlign)));
  2079. TestOptionsProvider options_provider;
  2080. SimpleBufferSerializer serializer(memory.get(),
  2081. PaintOpBuffer::kInitialBufferSize,
  2082. options_provider.serialize_options());
  2083. PaintOpBufferSerializer::Preamble preamble;
  2084. preamble.playback_rect = test_case.clip_rect;
  2085. preamble.full_raster_rect = gfx::Rect(0, 0, test_case.clip_rect.right(),
  2086. test_case.clip_rect.bottom());
  2087. // Avoid clearing.
  2088. preamble.content_size = gfx::Size(1000, 1000);
  2089. preamble.requires_clear = false;
  2090. serializer.SerializeAndDestroy(&buffer, nullptr, preamble);
  2091. ASSERT_NE(serializer.written(), 0u);
  2092. auto deserialized_buffer =
  2093. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  2094. options_provider.deserialize_options());
  2095. ASSERT_TRUE(deserialized_buffer);
  2096. auto deserialized_iter = PaintOpBuffer::Iterator(deserialized_buffer.get());
  2097. ASSERT_EQ((*deserialized_iter)->GetType(), PaintOpType::Save)
  2098. << PaintOpTypeToString((*deserialized_iter)->GetType());
  2099. ++deserialized_iter;
  2100. ASSERT_EQ((*deserialized_iter)->GetType(), PaintOpType::ClipRect)
  2101. << PaintOpTypeToString((*deserialized_iter)->GetType());
  2102. ++deserialized_iter;
  2103. if (test_case.should_draw) {
  2104. ASSERT_EQ((*deserialized_iter)->GetType(), PaintOpType::DrawImage)
  2105. << PaintOpTypeToString((*deserialized_iter)->GetType());
  2106. ++deserialized_iter;
  2107. }
  2108. ASSERT_EQ((*deserialized_iter)->GetType(), PaintOpType::Restore)
  2109. << PaintOpTypeToString((*deserialized_iter)->GetType());
  2110. ++deserialized_iter;
  2111. ASSERT_EQ(deserialized_iter.end(), deserialized_iter);
  2112. }
  2113. }
  2114. TEST(PaintOpBufferSerializationTest, AlphaFoldingDuringSerialization) {
  2115. PaintOpBuffer buffer;
  2116. float alpha = 0.4f;
  2117. buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
  2118. PaintFlags draw_flags;
  2119. draw_flags.setColor(SkColors::kMagenta);
  2120. draw_flags.setAlpha(50);
  2121. SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
  2122. buffer.push<DrawRectOp>(rect, draw_flags);
  2123. buffer.push<RestoreOp>();
  2124. PaintOpBufferSerializer::Preamble preamble;
  2125. preamble.content_size = gfx::Size(1000, 1000);
  2126. preamble.playback_rect = gfx::Rect(gfx::Size(100, 100));
  2127. preamble.full_raster_rect = preamble.playback_rect;
  2128. preamble.requires_clear = false;
  2129. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  2130. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  2131. PaintOpBuffer::PaintOpAlign)));
  2132. TestOptionsProvider options_provider;
  2133. SimpleBufferSerializer serializer(memory.get(),
  2134. PaintOpBuffer::kInitialBufferSize,
  2135. options_provider.serialize_options());
  2136. serializer.SerializeAndDestroy(&buffer, nullptr, preamble);
  2137. ASSERT_NE(serializer.written(), 0u);
  2138. auto deserialized_buffer =
  2139. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  2140. options_provider.deserialize_options());
  2141. ASSERT_TRUE(deserialized_buffer);
  2142. // 4 additional ops for save, clip, clear, and restore.
  2143. ASSERT_EQ(deserialized_buffer->size(), 4u);
  2144. size_t i = 0;
  2145. for (const auto* op : PaintOpBuffer::Iterator(deserialized_buffer.get())) {
  2146. ++i;
  2147. if (i == 1) {
  2148. EXPECT_EQ(op->GetType(), PaintOpType::Save);
  2149. continue;
  2150. }
  2151. if (i == 2) {
  2152. EXPECT_EQ(op->GetType(), PaintOpType::ClipRect);
  2153. continue;
  2154. }
  2155. if (i == 4) {
  2156. EXPECT_EQ(op->GetType(), PaintOpType::Restore);
  2157. continue;
  2158. }
  2159. ASSERT_EQ(op->GetType(), PaintOpType::DrawRect);
  2160. // Expect the alpha from the draw and the save layer to be folded together.
  2161. // Since alpha is stored in a uint8_t and gets rounded, so use tolerance.
  2162. float expected_alpha = alpha * 50;
  2163. EXPECT_LE(std::abs(expected_alpha -
  2164. static_cast<const DrawRectOp*>(op)->flags.getAlpha()),
  2165. 1.f);
  2166. }
  2167. }
  2168. // Test generic PaintOp deserializing failure cases.
  2169. TEST(PaintOpBufferTest, PaintOpDeserialize) {
  2170. static constexpr size_t kSize = sizeof(LargestPaintOp) + 100;
  2171. static constexpr size_t kAlign = PaintOpBuffer::PaintOpAlign;
  2172. std::unique_ptr<char, base::AlignedFreeDeleter> input_(
  2173. static_cast<char*>(base::AlignedAlloc(kSize, kAlign)));
  2174. std::unique_ptr<char, base::AlignedFreeDeleter> output_(
  2175. static_cast<char*>(base::AlignedAlloc(kSize, kAlign)));
  2176. PaintOpBuffer buffer;
  2177. buffer.push<DrawColorOp>(SkColors::kMagenta, SkBlendMode::kSrc);
  2178. PaintOpBuffer::Iterator iter(&buffer);
  2179. PaintOp* op = *iter;
  2180. ASSERT_TRUE(op);
  2181. TestOptionsProvider options_provider;
  2182. size_t bytes_written =
  2183. op->Serialize(input_.get(), kSize, options_provider.serialize_options(),
  2184. nullptr, SkM44(), SkM44());
  2185. ASSERT_GT(bytes_written, 0u);
  2186. // can deserialize from exactly the right size
  2187. size_t bytes_read = 0;
  2188. PaintOp* success =
  2189. PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), kSize,
  2190. &bytes_read, options_provider.deserialize_options());
  2191. ASSERT_TRUE(success);
  2192. EXPECT_EQ(bytes_written, bytes_read);
  2193. success->DestroyThis();
  2194. // fail to deserialize if skip goes past input size
  2195. // (the DeserializationFailures test above tests if the skip is lying)
  2196. for (size_t i = 0; i < bytes_written - 1; ++i)
  2197. EXPECT_FALSE(PaintOp::Deserialize(input_.get(), i, output_.get(), kSize,
  2198. &bytes_read,
  2199. options_provider.deserialize_options()));
  2200. // unaligned skips fail to deserialize
  2201. PaintOp* serialized = reinterpret_cast<PaintOp*>(input_.get());
  2202. EXPECT_EQ(0u, serialized->skip % kAlign);
  2203. serialized->skip -= 1;
  2204. EXPECT_FALSE(PaintOp::Deserialize(input_.get(), bytes_written, output_.get(),
  2205. kSize, &bytes_read,
  2206. options_provider.deserialize_options()));
  2207. serialized->skip += 1;
  2208. // bogus types fail to deserialize
  2209. serialized->type = static_cast<uint8_t>(PaintOpType::LastPaintOpType) + 1;
  2210. EXPECT_FALSE(PaintOp::Deserialize(input_.get(), bytes_written, output_.get(),
  2211. kSize, &bytes_read,
  2212. options_provider.deserialize_options()));
  2213. }
  2214. // Test that deserializing invalid SkClipOp enums fails silently.
  2215. // Skia release asserts on this in several places so these are not safe
  2216. // to pass through to the SkCanvas API.
  2217. TEST(PaintOpBufferTest, ValidateSkClip) {
  2218. size_t buffer_size = kBufferBytesPerOp;
  2219. std::unique_ptr<char, base::AlignedFreeDeleter> serialized(static_cast<char*>(
  2220. base::AlignedAlloc(buffer_size, PaintOpBuffer::PaintOpAlign)));
  2221. std::unique_ptr<char, base::AlignedFreeDeleter> deserialized(
  2222. static_cast<char*>(
  2223. base::AlignedAlloc(buffer_size, PaintOpBuffer::PaintOpAlign)));
  2224. PaintOpBuffer buffer;
  2225. // Successful first op.
  2226. SkPath path;
  2227. buffer.push<ClipPathOp>(path, SkClipOp::kMax_EnumValue, /*antialias=*/true,
  2228. UsePaintCache::kDisabled);
  2229. // Bad other ops.
  2230. SkClipOp bad_clip = static_cast<SkClipOp>(
  2231. static_cast<uint32_t>(SkClipOp::kMax_EnumValue) + 1);
  2232. buffer.push<ClipPathOp>(path, bad_clip, /*antialias=*/true,
  2233. UsePaintCache::kDisabled);
  2234. buffer.push<ClipRectOp>(test_rects[0], bad_clip, true);
  2235. buffer.push<ClipRRectOp>(test_rrects[0], bad_clip, false);
  2236. // SkClipOp is serialized to uint8_t (see WriteEnum). Values outside uint8_t
  2237. // would crash the serialization, so this is the max value that passes checked
  2238. // cast but will still fail validation during deserialization.
  2239. SkClipOp bad_clip_max = static_cast<SkClipOp>(static_cast<uint8_t>(~0));
  2240. buffer.push<ClipRectOp>(test_rects[1], bad_clip_max, false);
  2241. TestOptionsProvider options_provider;
  2242. int op_idx = 0;
  2243. for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) {
  2244. const PaintOp* op = *iter;
  2245. size_t bytes_written = op->Serialize(serialized.get(), buffer_size,
  2246. options_provider.serialize_options(),
  2247. nullptr, SkM44(), SkM44());
  2248. ASSERT_GT(bytes_written, 0u);
  2249. size_t bytes_read = 0;
  2250. PaintOp* written = PaintOp::Deserialize(
  2251. serialized.get(), bytes_written, deserialized.get(), buffer_size,
  2252. &bytes_read, options_provider.deserialize_options());
  2253. // First op should succeed. Other ops with bad enums should
  2254. // serialize correctly but fail to deserialize due to the bad
  2255. // SkClipOp enum.
  2256. if (!op_idx) {
  2257. EXPECT_TRUE(written) << "op: " << op_idx;
  2258. EXPECT_EQ(bytes_written, bytes_read);
  2259. written->DestroyThis();
  2260. } else {
  2261. EXPECT_FALSE(written) << "op: " << op_idx;
  2262. }
  2263. ++op_idx;
  2264. }
  2265. }
  2266. TEST(PaintOpBufferTest, ValidateSkBlendMode) {
  2267. size_t buffer_size = kBufferBytesPerOp;
  2268. std::unique_ptr<char, base::AlignedFreeDeleter> serialized(static_cast<char*>(
  2269. base::AlignedAlloc(buffer_size, PaintOpBuffer::PaintOpAlign)));
  2270. std::unique_ptr<char, base::AlignedFreeDeleter> deserialized(
  2271. static_cast<char*>(
  2272. base::AlignedAlloc(buffer_size, PaintOpBuffer::PaintOpAlign)));
  2273. PaintOpBuffer buffer;
  2274. // Successful first two ops.
  2275. buffer.push<DrawColorOp>(SkColors::kMagenta, SkBlendMode::kDstIn);
  2276. PaintFlags good_flags = test_flags[0];
  2277. good_flags.setBlendMode(SkBlendMode::kColorBurn);
  2278. buffer.push<DrawRectOp>(test_rects[0], good_flags);
  2279. // Modes that are not supported by drawColor or SkPaint.
  2280. SkBlendMode bad_modes_for_draw_color[] = {
  2281. SkBlendMode::kOverlay,
  2282. SkBlendMode::kDarken,
  2283. SkBlendMode::kLighten,
  2284. SkBlendMode::kColorDodge,
  2285. SkBlendMode::kColorBurn,
  2286. SkBlendMode::kHardLight,
  2287. SkBlendMode::kSoftLight,
  2288. SkBlendMode::kDifference,
  2289. SkBlendMode::kExclusion,
  2290. SkBlendMode::kMultiply,
  2291. SkBlendMode::kHue,
  2292. SkBlendMode::kSaturation,
  2293. SkBlendMode::kColor,
  2294. SkBlendMode::kLuminosity,
  2295. static_cast<SkBlendMode>(static_cast<uint8_t>(SkBlendMode::kLastMode) +
  2296. 1),
  2297. static_cast<SkBlendMode>(static_cast<uint8_t>(~0)),
  2298. };
  2299. SkBlendMode bad_modes_for_flags[] = {
  2300. static_cast<SkBlendMode>(static_cast<uint8_t>(SkBlendMode::kLastMode) +
  2301. 1),
  2302. static_cast<SkBlendMode>(static_cast<uint8_t>(~0)),
  2303. };
  2304. for (size_t i = 0; i < std::size(bad_modes_for_draw_color); ++i) {
  2305. buffer.push<DrawColorOp>(SkColors::kMagenta, bad_modes_for_draw_color[i]);
  2306. }
  2307. for (size_t i = 0; i < std::size(bad_modes_for_flags); ++i) {
  2308. PaintFlags flags = test_flags[i % test_flags.size()];
  2309. flags.setBlendMode(bad_modes_for_flags[i]);
  2310. buffer.push<DrawRectOp>(test_rects[i % test_rects.size()], flags);
  2311. }
  2312. TestOptionsProvider options_provider;
  2313. int op_idx = 0;
  2314. for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) {
  2315. const PaintOp* op = *iter;
  2316. size_t bytes_written = op->Serialize(serialized.get(), buffer_size,
  2317. options_provider.serialize_options(),
  2318. nullptr, SkM44(), SkM44());
  2319. ASSERT_GT(bytes_written, 0u);
  2320. size_t bytes_read = 0;
  2321. PaintOp* written = PaintOp::Deserialize(
  2322. serialized.get(), bytes_written, deserialized.get(), buffer_size,
  2323. &bytes_read, options_provider.deserialize_options());
  2324. // First two ops should succeed. Other ops with bad enums should
  2325. // serialize correctly but fail to deserialize due to the bad
  2326. // SkBlendMode enum.
  2327. if (op_idx < 2) {
  2328. EXPECT_TRUE(written) << "op: " << op_idx;
  2329. EXPECT_EQ(bytes_written, bytes_read);
  2330. written->DestroyThis();
  2331. } else {
  2332. EXPECT_FALSE(written) << "op: " << op_idx;
  2333. }
  2334. ++op_idx;
  2335. }
  2336. }
  2337. TEST(PaintOpBufferTest, ValidateRects) {
  2338. size_t buffer_size = kBufferBytesPerOp;
  2339. std::unique_ptr<char, base::AlignedFreeDeleter> serialized(static_cast<char*>(
  2340. base::AlignedAlloc(buffer_size, PaintOpBuffer::PaintOpAlign)));
  2341. std::unique_ptr<char, base::AlignedFreeDeleter> deserialized(
  2342. static_cast<char*>(
  2343. base::AlignedAlloc(buffer_size, PaintOpBuffer::PaintOpAlign)));
  2344. // Used for QuickRejectDraw
  2345. SkCanvas device(256, 256);
  2346. SkCanvas* canvas = &device;
  2347. SkRect bad_rect = SkRect::MakeEmpty();
  2348. bad_rect.fBottom = std::numeric_limits<float>::quiet_NaN();
  2349. EXPECT_FALSE(bad_rect.isFinite());
  2350. // Push all op variations that take rects.
  2351. PaintOpBuffer buffer;
  2352. buffer.push<AnnotateOp>(PaintCanvas::AnnotationType::URL, bad_rect,
  2353. SkData::MakeWithCString("test1"));
  2354. buffer.push<ClipRectOp>(bad_rect, SkClipOp::kDifference, true);
  2355. buffer.push<DrawImageRectOp>(test_images[0], bad_rect, test_rects[1],
  2356. SkCanvas::kStrict_SrcRectConstraint);
  2357. buffer.push<DrawImageRectOp>(test_images[0], test_rects[0], bad_rect,
  2358. SkCanvas::kStrict_SrcRectConstraint);
  2359. buffer.push<DrawOvalOp>(bad_rect, test_flags[0]);
  2360. buffer.push<DrawRectOp>(bad_rect, test_flags[0]);
  2361. buffer.push<SaveLayerOp>(&bad_rect, nullptr);
  2362. buffer.push<SaveLayerOp>(&bad_rect, &test_flags[0]);
  2363. buffer.push<SaveLayerAlphaOp>(&bad_rect, test_floats[0]);
  2364. TestOptionsProvider options_provider;
  2365. // Every op should serialize but fail to deserialize due to the bad rect.
  2366. int op_idx = 0;
  2367. for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) {
  2368. const PaintOp* op = *iter;
  2369. size_t bytes_written = op->Serialize(serialized.get(), buffer_size,
  2370. options_provider.serialize_options(),
  2371. nullptr, SkM44(), SkM44());
  2372. ASSERT_GT(bytes_written, 0u);
  2373. size_t bytes_read = 0;
  2374. PaintOp* written = PaintOp::Deserialize(
  2375. serialized.get(), bytes_written, deserialized.get(), buffer_size,
  2376. &bytes_read, options_provider.deserialize_options());
  2377. EXPECT_FALSE(written) << "op: " << op_idx;
  2378. // Additionally, every draw op should be rejected by QuickRejectDraw if
  2379. // the paint op buffer were played back directly without going through
  2380. // deserialization (e.g. canvas2D, crbug.com/1186392)
  2381. if (op->IsDrawOp()) {
  2382. EXPECT_TRUE(PaintOp::QuickRejectDraw(op, canvas));
  2383. }
  2384. ++op_idx;
  2385. }
  2386. }
  2387. TEST(PaintOpBufferTest, BoundingRect_DrawImageOp) {
  2388. PaintOpBuffer buffer;
  2389. PushDrawImageOps(&buffer);
  2390. SkRect rect;
  2391. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2392. auto* op = static_cast<DrawImageOp*>(base_op);
  2393. SkRect image_rect = SkRect::MakeXYWH(op->left, op->top, op->image.width(),
  2394. op->image.height());
  2395. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2396. EXPECT_EQ(rect, image_rect.makeSorted());
  2397. }
  2398. }
  2399. TEST(PaintOpBufferTest, BoundingRect_DrawImageRectOp) {
  2400. PaintOpBuffer buffer;
  2401. PushDrawImageRectOps(&buffer);
  2402. SkRect rect;
  2403. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2404. auto* op = static_cast<DrawImageRectOp*>(base_op);
  2405. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2406. EXPECT_EQ(rect, op->dst.makeSorted());
  2407. }
  2408. }
  2409. TEST(PaintOpBufferTest, BoundingRect_DrawIRectOp) {
  2410. PaintOpBuffer buffer;
  2411. PushDrawIRectOps(&buffer);
  2412. SkRect rect;
  2413. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2414. auto* op = static_cast<DrawIRectOp*>(base_op);
  2415. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2416. EXPECT_EQ(rect, SkRect::Make(op->rect).makeSorted());
  2417. }
  2418. }
  2419. TEST(PaintOpBufferTest, BoundingRect_DrawOvalOp) {
  2420. PaintOpBuffer buffer;
  2421. PushDrawOvalOps(&buffer);
  2422. SkRect rect;
  2423. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2424. auto* op = static_cast<DrawOvalOp*>(base_op);
  2425. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2426. EXPECT_EQ(rect, op->oval.makeSorted());
  2427. }
  2428. }
  2429. TEST(PaintOpBufferTest, BoundingRect_DrawPathOp) {
  2430. PaintOpBuffer buffer;
  2431. PushDrawPathOps(&buffer);
  2432. SkRect rect;
  2433. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2434. auto* op = static_cast<DrawPathOp*>(base_op);
  2435. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2436. EXPECT_EQ(rect, op->path.getBounds().makeSorted());
  2437. }
  2438. }
  2439. TEST(PaintOpBufferTest, BoundingRect_DrawRectOp) {
  2440. PaintOpBuffer buffer;
  2441. PushDrawRectOps(&buffer);
  2442. SkRect rect;
  2443. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2444. auto* op = static_cast<DrawRectOp*>(base_op);
  2445. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2446. EXPECT_EQ(rect, op->rect.makeSorted());
  2447. }
  2448. }
  2449. TEST(PaintOpBufferTest, BoundingRect_DrawRRectOp) {
  2450. PaintOpBuffer buffer;
  2451. PushDrawRRectOps(&buffer);
  2452. SkRect rect;
  2453. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2454. auto* op = static_cast<DrawRRectOp*>(base_op);
  2455. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2456. EXPECT_EQ(rect, op->rrect.rect().makeSorted());
  2457. }
  2458. }
  2459. TEST(PaintOpBufferTest, BoundingRect_DrawLineOp) {
  2460. PaintOpBuffer buffer;
  2461. PushDrawLineOps(&buffer);
  2462. SkRect rect;
  2463. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2464. auto* op = static_cast<DrawLineOp*>(base_op);
  2465. SkRect line_rect;
  2466. line_rect.fLeft = op->x0;
  2467. line_rect.fTop = op->y0;
  2468. line_rect.fRight = op->x1;
  2469. line_rect.fBottom = op->y1;
  2470. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2471. EXPECT_EQ(rect, line_rect.makeSorted());
  2472. }
  2473. }
  2474. TEST(PaintOpBufferTest, BoundingRect_DrawDRRectOp) {
  2475. PaintOpBuffer buffer;
  2476. PushDrawDRRectOps(&buffer);
  2477. SkRect rect;
  2478. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2479. auto* op = static_cast<DrawDRRectOp*>(base_op);
  2480. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2481. EXPECT_EQ(rect, op->outer.getBounds().makeSorted());
  2482. }
  2483. }
  2484. TEST(PaintOpBufferTest, BoundingRect_DrawTextBlobOp) {
  2485. PaintOpBuffer buffer;
  2486. PushDrawTextBlobOps(&buffer);
  2487. SkRect rect;
  2488. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  2489. auto* op = static_cast<DrawTextBlobOp*>(base_op);
  2490. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  2491. EXPECT_EQ(rect, op->blob->bounds().makeOffset(op->x, op->y).makeSorted());
  2492. }
  2493. }
  2494. class MockImageProvider : public ImageProvider {
  2495. public:
  2496. MockImageProvider() = default;
  2497. explicit MockImageProvider(bool fail_all_decodes)
  2498. : fail_all_decodes_(fail_all_decodes) {}
  2499. MockImageProvider(std::vector<SkSize> src_rect_offset,
  2500. std::vector<SkSize> scale,
  2501. std::vector<PaintFlags::FilterQuality> quality)
  2502. : src_rect_offset_(src_rect_offset), scale_(scale), quality_(quality) {}
  2503. ~MockImageProvider() override = default;
  2504. ImageProvider::ScopedResult GetRasterContent(
  2505. const DrawImage& draw_image) override {
  2506. decoded_images_.push_back(draw_image);
  2507. if (draw_image.paint_image().IsPaintWorklet())
  2508. return ScopedResult(record_);
  2509. if (fail_all_decodes_)
  2510. return ImageProvider::ScopedResult();
  2511. SkBitmap bitmap;
  2512. bitmap.allocPixelsFlags(SkImageInfo::MakeN32Premul(10, 10),
  2513. SkBitmap::kZeroPixels_AllocFlag);
  2514. sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
  2515. size_t i = index_++;
  2516. return ScopedResult(DecodedDrawImage(image, nullptr, src_rect_offset_[i],
  2517. scale_[i], quality_[i], true));
  2518. }
  2519. void SetRecord(sk_sp<PaintRecord> record) { record_ = std::move(record); }
  2520. const std::vector<DrawImage>& decoded_images() const {
  2521. return decoded_images_;
  2522. }
  2523. private:
  2524. std::vector<SkSize> src_rect_offset_;
  2525. std::vector<SkSize> scale_;
  2526. std::vector<PaintFlags::FilterQuality> quality_;
  2527. size_t index_ = 0;
  2528. bool fail_all_decodes_ = false;
  2529. sk_sp<PaintRecord> record_;
  2530. std::vector<DrawImage> decoded_images_;
  2531. };
  2532. TEST(PaintOpBufferTest, SkipsOpsOutsideClip) {
  2533. // All ops with images draw outside the clip and should be skipped. If any
  2534. // call is made to the ImageProvider, it should crash.
  2535. MockImageProvider image_provider;
  2536. PaintOpBuffer buffer;
  2537. // Apply a clip outside the region for images.
  2538. buffer.push<ClipRectOp>(SkRect::MakeXYWH(0, 0, 100, 100),
  2539. SkClipOp::kIntersect, false);
  2540. PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
  2541. buffer.push<DrawImageOp>(paint_image, 105.0f, 105.0f);
  2542. PaintFlags image_flags;
  2543. image_flags.setShader(PaintShader::MakeImage(paint_image, SkTileMode::kRepeat,
  2544. SkTileMode::kRepeat, nullptr));
  2545. buffer.push<DrawRectOp>(SkRect::MakeXYWH(110, 110, 100, 100), image_flags);
  2546. SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100);
  2547. buffer.push<DrawRectOp>(rect, PaintFlags());
  2548. // The single save/restore call is from the PaintOpBuffer's use of
  2549. // SkAutoRestoreCanvas.
  2550. testing::StrictMock<MockCanvas> canvas;
  2551. testing::Sequence s;
  2552. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2553. EXPECT_CALL(canvas, OnDrawRectWithColor(_)).InSequence(s);
  2554. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2555. buffer.Playback(&canvas, PlaybackParams(&image_provider));
  2556. }
  2557. TEST(PaintOpBufferTest, SkipsOpsWithFailedDecodes) {
  2558. MockImageProvider image_provider(true);
  2559. PaintOpBuffer buffer;
  2560. PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
  2561. buffer.push<DrawImageOp>(paint_image, 105.0f, 105.0f);
  2562. PaintFlags image_flags;
  2563. image_flags.setShader(PaintShader::MakeImage(paint_image, SkTileMode::kRepeat,
  2564. SkTileMode::kRepeat, nullptr));
  2565. buffer.push<DrawRectOp>(SkRect::MakeXYWH(110, 110, 100, 100), image_flags);
  2566. buffer.push<DrawColorOp>(SkColors::kRed, SkBlendMode::kSrcOver);
  2567. testing::StrictMock<MockCanvas> canvas;
  2568. testing::Sequence s;
  2569. EXPECT_CALL(canvas, OnDrawPaintWithColor(_)).InSequence(s);
  2570. buffer.Playback(&canvas, PlaybackParams(&image_provider));
  2571. }
  2572. MATCHER(NonLazyImage, "") {
  2573. return !arg->isLazyGenerated();
  2574. }
  2575. MATCHER_P(MatchesPaintImage, paint_image, "") {
  2576. return arg.paint_image() == paint_image;
  2577. }
  2578. MATCHER_P2(MatchesRect, rect, scale, "") {
  2579. EXPECT_EQ(arg.x(), rect.x() * scale.width());
  2580. EXPECT_EQ(arg.y(), rect.y() * scale.height());
  2581. EXPECT_EQ(arg.width(), rect.width() * scale.width());
  2582. EXPECT_EQ(arg.height(), rect.height() * scale.height());
  2583. return true;
  2584. }
  2585. MATCHER_P(MatchesQuality, quality, "") {
  2586. return quality == arg->getFilterQuality();
  2587. }
  2588. MATCHER_P2(MatchesShader, flags, scale, "") {
  2589. SkMatrix matrix;
  2590. SkTileMode xy[2];
  2591. SkImage* image = arg.getShader()->isAImage(&matrix, xy);
  2592. EXPECT_FALSE(image->isLazyGenerated());
  2593. SkSize local_scale;
  2594. matrix.decomposeScale(&local_scale, nullptr);
  2595. EXPECT_EQ(local_scale.width(), 1.0f / scale.width());
  2596. EXPECT_EQ(local_scale.height(), 1.0f / scale.height());
  2597. EXPECT_EQ(flags.getShader()->tx(), xy[0]);
  2598. EXPECT_EQ(flags.getShader()->ty(), xy[1]);
  2599. return true;
  2600. }
  2601. TEST(PaintOpBufferTest, RasterPaintWorkletImageRectBasicCase) {
  2602. sk_sp<PaintOpBuffer> paint_worklet_buffer = sk_make_sp<PaintOpBuffer>();
  2603. PaintFlags noop_flags;
  2604. SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 100, 100);
  2605. paint_worklet_buffer->push<TranslateOp>(8.0f, 8.0f);
  2606. paint_worklet_buffer->push<SaveLayerOp>(&savelayer_rect, &noop_flags);
  2607. PaintFlags draw_flags;
  2608. draw_flags.setColor(0u);
  2609. SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100);
  2610. paint_worklet_buffer->push<DrawRectOp>(rect, draw_flags);
  2611. MockImageProvider provider;
  2612. provider.SetRecord(paint_worklet_buffer);
  2613. PaintOpBuffer blink_buffer;
  2614. scoped_refptr<TestPaintWorkletInput> input =
  2615. base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100, 100));
  2616. PaintImage image = CreatePaintWorkletPaintImage(input);
  2617. SkRect src = SkRect::MakeXYWH(0, 0, 100, 100);
  2618. SkRect dst = SkRect::MakeXYWH(0, 0, 100, 100);
  2619. blink_buffer.push<DrawImageRectOp>(image, src, dst,
  2620. SkCanvas::kStrict_SrcRectConstraint);
  2621. testing::StrictMock<MockCanvas> canvas;
  2622. testing::Sequence s;
  2623. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2624. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  2625. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2626. EXPECT_CALL(canvas, didTranslate(8.0f, 8.0f));
  2627. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  2628. EXPECT_CALL(canvas, OnDrawRectWithColor(0u));
  2629. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2630. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2631. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2632. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2633. blink_buffer.Playback(&canvas, PlaybackParams(&provider));
  2634. }
  2635. TEST(PaintOpBufferTest, RasterPaintWorkletImageRectTranslated) {
  2636. sk_sp<PaintOpBuffer> paint_worklet_buffer = sk_make_sp<PaintOpBuffer>();
  2637. PaintFlags noop_flags;
  2638. SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 10, 10);
  2639. paint_worklet_buffer->push<SaveLayerOp>(&savelayer_rect, &noop_flags);
  2640. PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
  2641. paint_worklet_buffer->push<DrawImageOp>(
  2642. paint_image, 0.0f, 0.0f, SkSamplingOptions(SkFilterMode::kLinear),
  2643. nullptr);
  2644. std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
  2645. std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)};
  2646. std::vector<PaintFlags::FilterQuality> quality = {
  2647. PaintFlags::FilterQuality::kHigh};
  2648. MockImageProvider provider(src_rect_offset, scale_adjustment, quality);
  2649. provider.SetRecord(paint_worklet_buffer);
  2650. PaintOpBuffer blink_buffer;
  2651. scoped_refptr<TestPaintWorkletInput> input =
  2652. base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100, 100));
  2653. PaintImage image = CreatePaintWorkletPaintImage(input);
  2654. SkRect src = SkRect::MakeXYWH(0, 0, 100, 100);
  2655. SkRect dst = SkRect::MakeXYWH(5, 7, 100, 100);
  2656. blink_buffer.push<DrawImageRectOp>(image, src, dst,
  2657. SkCanvas::kStrict_SrcRectConstraint);
  2658. testing::StrictMock<MockCanvas> canvas;
  2659. testing::Sequence s;
  2660. SkSamplingOptions sampling({0, 1.0f / 2});
  2661. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2662. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  2663. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  2664. EXPECT_CALL(canvas, didConcat44(SkM44::Translate(5.0f, 7.0f)));
  2665. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2666. EXPECT_CALL(canvas, didScale(1.0f / scale_adjustment[0].width(),
  2667. 1.0f / scale_adjustment[0].height()));
  2668. EXPECT_CALL(canvas, onDrawImage2(NonLazyImage(), 0.0f, 0.0f, sampling, _));
  2669. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2670. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2671. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2672. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2673. blink_buffer.Playback(&canvas, PlaybackParams(&provider));
  2674. }
  2675. TEST(PaintOpBufferTest, RasterPaintWorkletImageRectScaled) {
  2676. sk_sp<PaintOpBuffer> paint_worklet_buffer = sk_make_sp<PaintOpBuffer>();
  2677. PaintFlags noop_flags;
  2678. SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 10, 10);
  2679. paint_worklet_buffer->push<SaveLayerOp>(&savelayer_rect, &noop_flags);
  2680. PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
  2681. paint_worklet_buffer->push<DrawImageOp>(
  2682. paint_image, 0.0f, 0.0f, SkSamplingOptions(SkFilterMode::kLinear),
  2683. nullptr);
  2684. std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
  2685. std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)};
  2686. std::vector<PaintFlags::FilterQuality> quality = {
  2687. PaintFlags::FilterQuality::kHigh};
  2688. MockImageProvider provider(src_rect_offset, scale_adjustment, quality);
  2689. provider.SetRecord(paint_worklet_buffer);
  2690. PaintOpBuffer blink_buffer;
  2691. scoped_refptr<TestPaintWorkletInput> input =
  2692. base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100, 100));
  2693. PaintImage image = CreatePaintWorkletPaintImage(input);
  2694. SkRect src = SkRect::MakeXYWH(0, 0, 100, 100);
  2695. SkRect dst = SkRect::MakeXYWH(0, 0, 200, 150);
  2696. blink_buffer.push<DrawImageRectOp>(image, src, dst,
  2697. SkCanvas::kStrict_SrcRectConstraint);
  2698. testing::StrictMock<MockCanvas> canvas;
  2699. testing::Sequence s;
  2700. SkSamplingOptions sampling({0, 1.0f / 2});
  2701. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2702. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  2703. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  2704. EXPECT_CALL(canvas, didConcat44(SkM44::Scale(2.f, 1.5f)));
  2705. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2706. EXPECT_CALL(canvas, didScale(1.0f / scale_adjustment[0].width(),
  2707. 1.0f / scale_adjustment[0].height()));
  2708. EXPECT_CALL(canvas, onDrawImage2(NonLazyImage(), 0.0f, 0.0f, sampling, _));
  2709. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2710. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2711. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2712. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2713. blink_buffer.Playback(&canvas, PlaybackParams(&provider));
  2714. }
  2715. TEST(PaintOpBufferTest, RasterPaintWorkletImageRectClipped) {
  2716. sk_sp<PaintOpBuffer> paint_worklet_buffer = sk_make_sp<PaintOpBuffer>();
  2717. PaintFlags noop_flags;
  2718. SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 60, 60);
  2719. paint_worklet_buffer->push<SaveLayerOp>(&savelayer_rect, &noop_flags);
  2720. SkSamplingOptions linear(SkFilterMode::kLinear);
  2721. PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
  2722. // One rect inside the src-rect, one outside.
  2723. paint_worklet_buffer->push<DrawImageOp>(paint_image, 0.0f, 0.0f, linear,
  2724. nullptr);
  2725. paint_worklet_buffer->push<DrawImageOp>(paint_image, 50.0f, 50.0f, linear,
  2726. nullptr);
  2727. std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
  2728. std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)};
  2729. std::vector<PaintFlags::FilterQuality> quality = {
  2730. PaintFlags::FilterQuality::kHigh};
  2731. MockImageProvider provider(src_rect_offset, scale_adjustment, quality);
  2732. provider.SetRecord(paint_worklet_buffer);
  2733. PaintOpBuffer blink_buffer;
  2734. scoped_refptr<TestPaintWorkletInput> input =
  2735. base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100, 100));
  2736. PaintImage image = CreatePaintWorkletPaintImage(input);
  2737. SkRect src = SkRect::MakeXYWH(0, 0, 20, 20);
  2738. SkRect dst = SkRect::MakeXYWH(0, 0, 20, 20);
  2739. blink_buffer.push<DrawImageRectOp>(image, src, dst,
  2740. SkCanvas::kStrict_SrcRectConstraint);
  2741. testing::StrictMock<MockCanvas> canvas;
  2742. testing::Sequence s;
  2743. SkSamplingOptions sampling({0, 1.0f / 2});
  2744. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2745. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  2746. EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
  2747. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2748. EXPECT_CALL(canvas, didScale(1.0f / scale_adjustment[0].width(),
  2749. 1.0f / scale_adjustment[0].height()));
  2750. EXPECT_CALL(canvas, onDrawImage2(NonLazyImage(), 0.0f, 0.0f, sampling, _));
  2751. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2752. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2753. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2754. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2755. blink_buffer.Playback(&canvas, PlaybackParams(&provider));
  2756. }
  2757. TEST(PaintOpBufferTest, ReplacesImagesFromProvider) {
  2758. std::vector<SkSize> src_rect_offset = {
  2759. SkSize::MakeEmpty(), SkSize::Make(2.0f, 2.0f), SkSize::Make(3.0f, 3.0f)};
  2760. std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f),
  2761. SkSize::Make(0.3f, 0.3f),
  2762. SkSize::Make(0.4f, 0.4f)};
  2763. std::vector<PaintFlags::FilterQuality> quality = {
  2764. PaintFlags::FilterQuality::kHigh, PaintFlags::FilterQuality::kMedium,
  2765. PaintFlags::FilterQuality::kHigh};
  2766. MockImageProvider image_provider(src_rect_offset, scale_adjustment, quality);
  2767. PaintOpBuffer buffer;
  2768. SkRect rect = SkRect::MakeWH(10, 10);
  2769. SkSamplingOptions sampling(SkFilterMode::kLinear);
  2770. PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
  2771. buffer.push<DrawImageOp>(paint_image, 0.0f, 0.0f, sampling, nullptr);
  2772. buffer.push<DrawImageRectOp>(paint_image, rect, rect, sampling, nullptr,
  2773. SkCanvas::kFast_SrcRectConstraint);
  2774. PaintFlags flags;
  2775. flags.setShader(PaintShader::MakeImage(paint_image, SkTileMode::kRepeat,
  2776. SkTileMode::kRepeat, nullptr));
  2777. buffer.push<DrawOvalOp>(SkRect::MakeWH(10, 10), flags);
  2778. testing::StrictMock<MockCanvas> canvas;
  2779. testing::Sequence s;
  2780. SkSamplingOptions sampling0({0, 1.0f / 2});
  2781. SkSamplingOptions sampling1(SkFilterMode::kLinear, SkMipmapMode::kNearest);
  2782. // Save/scale/image/restore from DrawImageop.
  2783. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2784. EXPECT_CALL(canvas, didScale(1.0f / scale_adjustment[0].width(),
  2785. 1.0f / scale_adjustment[0].height()));
  2786. EXPECT_CALL(canvas, onDrawImage2(NonLazyImage(), 0.0f, 0.0f, sampling0, _));
  2787. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2788. // DrawImageRectop.
  2789. SkRect src_rect =
  2790. rect.makeOffset(src_rect_offset[1].width(), src_rect_offset[1].height());
  2791. EXPECT_CALL(canvas,
  2792. onDrawImageRect2(NonLazyImage(),
  2793. MatchesRect(src_rect, scale_adjustment[1]),
  2794. SkRect::MakeWH(10, 10), sampling1, _,
  2795. SkCanvas::kFast_SrcRectConstraint));
  2796. // DrawOvalop.
  2797. EXPECT_CALL(canvas, onDrawOval(SkRect::MakeWH(10, 10),
  2798. MatchesShader(flags, scale_adjustment[2])));
  2799. buffer.Playback(&canvas, PlaybackParams(&image_provider));
  2800. }
  2801. TEST(PaintOpBufferTest, DrawImageRectOpWithLooperNoImageProvider) {
  2802. PaintOpBuffer buffer;
  2803. PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100));
  2804. SkLayerDrawLooper::Builder sk_draw_looper_builder;
  2805. sk_draw_looper_builder.addLayer(20.0, 20.0);
  2806. SkLayerDrawLooper::LayerInfo info_unmodified;
  2807. sk_draw_looper_builder.addLayerOnTop(info_unmodified);
  2808. PaintFlags paint_flags;
  2809. paint_flags.setLooper(sk_draw_looper_builder.detach());
  2810. buffer.push<DrawImageRectOp>(image, SkRect::MakeWH(100, 100),
  2811. SkRect::MakeWH(100, 100), SkSamplingOptions(),
  2812. &paint_flags, SkCanvas::kFast_SrcRectConstraint);
  2813. testing::StrictMock<MockCanvas> canvas;
  2814. EXPECT_CALL(canvas, willSave);
  2815. EXPECT_CALL(canvas, didTranslate);
  2816. EXPECT_CALL(canvas, willRestore);
  2817. EXPECT_CALL(canvas, onDrawImageRect2).Times(2);
  2818. buffer.Playback(&canvas, PlaybackParams(nullptr));
  2819. }
  2820. TEST(PaintOpBufferTest, DrawImageRectOpWithLooperWithImageProvider) {
  2821. PaintOpBuffer buffer;
  2822. PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100));
  2823. SkLayerDrawLooper::Builder sk_draw_looper_builder;
  2824. sk_draw_looper_builder.addLayer(20.0, 20.0);
  2825. SkLayerDrawLooper::LayerInfo info_unmodified;
  2826. sk_draw_looper_builder.addLayerOnTop(info_unmodified);
  2827. PaintFlags paint_flags;
  2828. paint_flags.setLooper(sk_draw_looper_builder.detach());
  2829. buffer.push<DrawImageRectOp>(image, SkRect::MakeWH(100, 100),
  2830. SkRect::MakeWH(100, 100), SkSamplingOptions(),
  2831. &paint_flags, SkCanvas::kFast_SrcRectConstraint);
  2832. testing::StrictMock<MockCanvas> canvas;
  2833. EXPECT_CALL(canvas, willSave);
  2834. EXPECT_CALL(canvas, didTranslate);
  2835. EXPECT_CALL(canvas, willRestore);
  2836. EXPECT_CALL(canvas, onDrawImageRect2).Times(2);
  2837. std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
  2838. std::vector<SkSize> scale_adjustment = {SkSize::Make(1.0f, 1.0f)};
  2839. std::vector<PaintFlags::FilterQuality> quality = {
  2840. PaintFlags::FilterQuality::kHigh};
  2841. MockImageProvider image_provider(src_rect_offset, scale_adjustment, quality);
  2842. buffer.Playback(&canvas, PlaybackParams(&image_provider));
  2843. }
  2844. TEST(PaintOpBufferTest, ReplacesImagesFromProviderOOP) {
  2845. PaintOpBuffer buffer;
  2846. SkSize expected_scale = SkSize::Make(0.2f, 0.5f);
  2847. SkRect rect = SkRect::MakeWH(10, 10);
  2848. PaintFlags flags;
  2849. SkSamplingOptions sampling(SkFilterMode::kLinear);
  2850. PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
  2851. buffer.push<ScaleOp>(expected_scale.width(), expected_scale.height());
  2852. buffer.push<DrawImageOp>(paint_image, 0.0f, 0.0f, sampling, nullptr);
  2853. buffer.push<DrawImageRectOp>(paint_image, rect, rect, sampling, nullptr,
  2854. SkCanvas::kFast_SrcRectConstraint);
  2855. flags.setShader(PaintShader::MakeImage(paint_image, SkTileMode::kRepeat,
  2856. SkTileMode::kRepeat, nullptr));
  2857. buffer.push<DrawOvalOp>(SkRect::MakeWH(10, 10), flags);
  2858. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  2859. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  2860. PaintOpBuffer::PaintOpAlign)));
  2861. TestOptionsProvider options_provider;
  2862. SimpleBufferSerializer serializer(memory.get(),
  2863. PaintOpBuffer::kInitialBufferSize,
  2864. options_provider.serialize_options());
  2865. serializer.Serialize(&buffer);
  2866. ASSERT_NE(serializer.written(), 0u);
  2867. auto deserialized_buffer =
  2868. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  2869. options_provider.deserialize_options());
  2870. ASSERT_TRUE(deserialized_buffer);
  2871. for (auto* op : PaintOpBuffer::Iterator(deserialized_buffer.get())) {
  2872. testing::NiceMock<MockCanvas> canvas;
  2873. PlaybackParams params(nullptr);
  2874. testing::Sequence s;
  2875. if (op->GetType() == PaintOpType::DrawImage) {
  2876. // Save/scale/image/restore from DrawImageop.
  2877. EXPECT_CALL(canvas, willSave()).InSequence(s);
  2878. EXPECT_CALL(canvas, didScale(1.0f / expected_scale.width(),
  2879. 1.0f / expected_scale.height()));
  2880. EXPECT_CALL(canvas, onDrawImage2(NonLazyImage(), 0.0f, 0.0f, _, _));
  2881. EXPECT_CALL(canvas, willRestore()).InSequence(s);
  2882. op->Raster(&canvas, params);
  2883. } else if (op->GetType() == PaintOpType::DrawImageRect) {
  2884. EXPECT_CALL(canvas, onDrawImageRect2(NonLazyImage(),
  2885. MatchesRect(rect, expected_scale),
  2886. SkRect::MakeWH(10, 10), _, _,
  2887. SkCanvas::kFast_SrcRectConstraint));
  2888. op->Raster(&canvas, params);
  2889. } else if (op->GetType() == PaintOpType::DrawOval) {
  2890. EXPECT_CALL(canvas, onDrawOval(SkRect::MakeWH(10, 10),
  2891. MatchesShader(flags, expected_scale)));
  2892. op->Raster(&canvas, params);
  2893. }
  2894. }
  2895. }
  2896. class PaintFilterSerializationTest : public ::testing::TestWithParam<bool> {};
  2897. INSTANTIATE_TEST_SUITE_P(PaintFilterSerializationTests,
  2898. PaintFilterSerializationTest,
  2899. ::testing::Values(true, false));
  2900. TEST_P(PaintFilterSerializationTest, Basic) {
  2901. SkScalar scalars[9] = {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f};
  2902. std::vector<sk_sp<PaintFilter>> filters = {
  2903. sk_sp<PaintFilter>{new ColorFilterPaintFilter(
  2904. SkColorFilters::LinearToSRGBGamma(), nullptr)},
  2905. sk_sp<PaintFilter>{
  2906. new BlurPaintFilter(0.5f, 0.3f, SkTileMode::kRepeat, nullptr)},
  2907. sk_sp<PaintFilter>{new DropShadowPaintFilter(
  2908. 5.f, 10.f, 0.1f, 0.3f, SkColors::kBlue,
  2909. DropShadowPaintFilter::ShadowMode::kDrawShadowOnly, nullptr)},
  2910. sk_sp<PaintFilter>{new MagnifierPaintFilter(SkRect::MakeXYWH(5, 6, 7, 8),
  2911. 10.5f, nullptr)},
  2912. sk_sp<PaintFilter>{new AlphaThresholdPaintFilter(
  2913. SkRegion(SkIRect::MakeXYWH(0, 0, 100, 200)), 10.f, 20.f, nullptr)},
  2914. sk_sp<PaintFilter>{new MatrixConvolutionPaintFilter(
  2915. SkISize::Make(3, 3), scalars, 30.f, 123.f, SkIPoint::Make(0, 0),
  2916. SkTileMode::kDecal, true, nullptr)},
  2917. sk_sp<PaintFilter>{new MorphologyPaintFilter(
  2918. MorphologyPaintFilter::MorphType::kErode, 15.5f, 30.2f, nullptr)},
  2919. sk_sp<PaintFilter>{new OffsetPaintFilter(-1.f, -2.f, nullptr)},
  2920. sk_sp<PaintFilter>{new TilePaintFilter(
  2921. SkRect::MakeXYWH(1, 2, 3, 4), SkRect::MakeXYWH(4, 3, 2, 1), nullptr)},
  2922. sk_sp<PaintFilter>{new TurbulencePaintFilter(
  2923. TurbulencePaintFilter::TurbulenceType::kFractalNoise, 3.3f, 4.4f, 2,
  2924. 123, nullptr)},
  2925. sk_sp<PaintFilter>{new MatrixPaintFilter(
  2926. SkMatrix::I(), PaintFlags::FilterQuality::kHigh, nullptr)},
  2927. sk_sp<PaintFilter>{new LightingDistantPaintFilter(
  2928. PaintFilter::LightingType::kSpecular, SkPoint3::Make(1, 2, 3),
  2929. SkColors::kCyan, 1.1f, 2.2f, 3.3f, nullptr)},
  2930. sk_sp<PaintFilter>{new LightingPointPaintFilter(
  2931. PaintFilter::LightingType::kDiffuse, SkPoint3::Make(2, 3, 4),
  2932. SkColors::kRed, 1.2f, 3.4f, 5.6f, nullptr)},
  2933. sk_sp<PaintFilter>{new LightingSpotPaintFilter(
  2934. PaintFilter::LightingType::kSpecular, SkPoint3::Make(100, 200, 300),
  2935. SkPoint3::Make(400, 500, 600), 1, 2, SkColors::kMagenta, 3, 4, 5,
  2936. nullptr)},
  2937. sk_sp<PaintFilter>{
  2938. new ImagePaintFilter(CreateDiscardablePaintImage(gfx::Size(100, 100)),
  2939. SkRect::MakeWH(50, 50), SkRect::MakeWH(70, 70),
  2940. PaintFlags::FilterQuality::kMedium)}};
  2941. filters.emplace_back(new ComposePaintFilter(filters[0], filters[1]));
  2942. filters.emplace_back(
  2943. new XfermodePaintFilter(SkBlendMode::kDst, filters[2], filters[3]));
  2944. filters.emplace_back(new ArithmeticPaintFilter(1.1f, 2.2f, 3.3f, 4.4f, false,
  2945. filters[4], filters[5]));
  2946. filters.emplace_back(new DisplacementMapEffectPaintFilter(
  2947. SkColorChannel::kR, SkColorChannel::kG, 10, filters[6], filters[7]));
  2948. filters.emplace_back(new MergePaintFilter(filters.data(), filters.size()));
  2949. filters.emplace_back(new RecordPaintFilter(
  2950. sk_sp<PaintRecord>{new PaintRecord}, SkRect::MakeXYWH(10, 15, 20, 25)));
  2951. // Use a non-identity ctm to confirm that RecordPaintFilters are converted
  2952. // from raster-at-scale to fixed scale properly.
  2953. float scale_x = 2.f;
  2954. float scale_y = 3.f;
  2955. SkM44 ctm = SkM44::Scale(scale_x, scale_y);
  2956. TestOptionsProvider options_provider;
  2957. for (size_t i = 0; i < filters.size(); ++i) {
  2958. SCOPED_TRACE(i);
  2959. auto& filter = filters[i];
  2960. std::vector<uint8_t> memory;
  2961. size_t buffer_size = filter->type() == PaintFilter::Type::kPaintRecord
  2962. ? PaintOpBuffer::kInitialBufferSize
  2963. : PaintFilter::GetFilterSize(filter.get());
  2964. buffer_size += PaintOpWriter::HeaderBytes();
  2965. memory.resize(buffer_size);
  2966. PaintOpWriter writer(memory.data(), memory.size(),
  2967. options_provider.serialize_options(), GetParam());
  2968. writer.Write(filter.get(), ctm);
  2969. ASSERT_GT(writer.size(), 0u) << PaintFilter::TypeToString(filter->type());
  2970. sk_sp<PaintFilter> deserialized_filter;
  2971. PaintOpReader reader(memory.data(), writer.size(),
  2972. options_provider.deserialize_options(), GetParam());
  2973. reader.Read(&deserialized_filter);
  2974. ASSERT_TRUE(deserialized_filter);
  2975. if (filter->type() == PaintFilter::Type::kPaintRecord) {
  2976. // The filter's scaling behavior should be converted to kFixedScale so
  2977. // they are no longer equal.
  2978. ASSERT_EQ(deserialized_filter->type(), PaintFilter::Type::kPaintRecord);
  2979. const RecordPaintFilter& expected =
  2980. static_cast<const RecordPaintFilter&>(*filter);
  2981. const RecordPaintFilter& actual =
  2982. static_cast<const RecordPaintFilter&>(*deserialized_filter);
  2983. EXPECT_EQ(actual.scaling_behavior(),
  2984. RecordPaintFilter::ScalingBehavior::kFixedScale);
  2985. SkRect expected_bounds =
  2986. SkRect::MakeXYWH(scale_x * expected.record_bounds().x(),
  2987. scale_y * expected.record_bounds().y(),
  2988. scale_x * expected.record_bounds().width(),
  2989. scale_y * expected.record_bounds().height());
  2990. EXPECT_EQ(actual.record_bounds(), expected_bounds);
  2991. EXPECT_EQ(actual.raster_scale().width(), scale_x);
  2992. EXPECT_EQ(actual.raster_scale().height(), scale_y);
  2993. // And the first op in the deserialized filter's record should be a
  2994. // ScaleOp containing the extracted scale factors (if there's no
  2995. // security constraints that disable record serialization)
  2996. if (!GetParam()) {
  2997. const ScaleOp* scale = actual.record()->GetOpAtForTesting<ScaleOp>(0);
  2998. ASSERT_TRUE(scale);
  2999. EXPECT_EQ(scale->sx, scale_x);
  3000. EXPECT_EQ(scale->sy, scale_y);
  3001. }
  3002. } else {
  3003. EXPECT_TRUE(*filter == *deserialized_filter);
  3004. }
  3005. }
  3006. }
  3007. TEST(PaintOpBufferTest, PaintRecordShaderSerialization) {
  3008. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3009. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3010. PaintOpBuffer::PaintOpAlign)));
  3011. sk_sp<PaintOpBuffer> record_buffer(new PaintOpBuffer);
  3012. record_buffer->push<DrawRectOp>(SkRect::MakeXYWH(0, 0, 1, 1), PaintFlags());
  3013. TestOptionsProvider options_provider;
  3014. PaintFlags flags;
  3015. flags.setShader(PaintShader::MakePaintRecord(
  3016. record_buffer, SkRect::MakeWH(10, 10), SkTileMode::kClamp,
  3017. SkTileMode::kRepeat, nullptr));
  3018. PaintOpBuffer buffer;
  3019. buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 2, 3, 4), flags);
  3020. SimpleBufferSerializer serializer(memory.get(),
  3021. PaintOpBuffer::kInitialBufferSize,
  3022. options_provider.serialize_options());
  3023. serializer.Serialize(&buffer);
  3024. ASSERT_TRUE(serializer.valid());
  3025. ASSERT_GT(serializer.written(), 0u);
  3026. auto deserialized_buffer =
  3027. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  3028. options_provider.deserialize_options());
  3029. ASSERT_TRUE(deserialized_buffer);
  3030. PaintOpBuffer::Iterator it(deserialized_buffer.get());
  3031. ASSERT_TRUE(it);
  3032. auto* op = *it;
  3033. ASSERT_TRUE(op->GetType() == PaintOpType::DrawRect);
  3034. auto* rect_op = static_cast<DrawRectOp*>(op);
  3035. EXPECT_SKRECT_EQ(rect_op->rect, SkRect::MakeXYWH(1, 2, 3, 4));
  3036. EXPECT_TRUE(rect_op->flags == flags);
  3037. EXPECT_TRUE(*rect_op->flags.getShader() == *flags.getShader());
  3038. }
  3039. #if BUILDFLAG(SKIA_SUPPORT_SKOTTIE)
  3040. TEST(PaintOpBufferTest, BoundingRect_DrawSkottieOp) {
  3041. PaintOpBuffer buffer;
  3042. PushDrawSkottieOps(&buffer);
  3043. SkRect rect;
  3044. for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
  3045. auto* op = static_cast<DrawSkottieOp*>(base_op);
  3046. ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
  3047. EXPECT_EQ(rect, op->dst.makeSorted());
  3048. }
  3049. }
  3050. // Skottie-specific deserialization failure case.
  3051. TEST(PaintOpBufferTest,
  3052. DrawSkottieOpSerializationFailureFromUnPrivilegedProcess) {
  3053. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3054. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3055. PaintOpBuffer::PaintOpAlign)));
  3056. scoped_refptr<SkottieWrapper> skottie =
  3057. CreateSkottie(gfx::Size(100, 100), /*duration_secs=*/1);
  3058. ASSERT_TRUE(skottie->is_valid());
  3059. const SkRect input_rect = SkRect::MakeIWH(400, 300);
  3060. const float input_t = 0.4f;
  3061. PaintOpBuffer buffer;
  3062. buffer.push<DrawSkottieOp>(
  3063. skottie, input_rect, input_t,
  3064. GetTestImagesForSkottie(*skottie, input_rect,
  3065. PaintFlags::FilterQuality::kHigh, input_t),
  3066. SkottieColorMap(), SkottieTextPropertyValueMap());
  3067. // Serialize
  3068. TestOptionsProvider options_provider;
  3069. SimpleBufferSerializer serializer(memory.get(),
  3070. PaintOpBuffer::kInitialBufferSize,
  3071. options_provider.serialize_options());
  3072. serializer.Serialize(&buffer);
  3073. ASSERT_TRUE(serializer.valid());
  3074. ASSERT_GT(serializer.written(), 0u);
  3075. // De-Serialize
  3076. PaintOp::DeserializeOptions d_options(options_provider.deserialize_options());
  3077. // Deserialization should fail on a non privileged process.
  3078. d_options.is_privileged = false;
  3079. auto deserialized_buffer = PaintOpBuffer::MakeFromMemory(
  3080. memory.get(), serializer.written(), d_options);
  3081. ASSERT_FALSE(deserialized_buffer);
  3082. }
  3083. TEST(PaintOpBufferTest, DrawSkottieOpRasterWithoutImageAssets) {
  3084. scoped_refptr<SkottieWrapper> skottie =
  3085. CreateSkottie(gfx::Size(100, 100), /*duration_secs=*/5);
  3086. SkRect skottie_rect = SkRect::MakeWH(100, 100);
  3087. DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.1,
  3088. /*images=*/SkottieFrameDataMap(), SkottieColorMap(),
  3089. SkottieTextPropertyValueMap());
  3090. PlaybackParams playback_params(/*image_provider=*/nullptr);
  3091. {
  3092. NiceMock<MockCanvas> canvas;
  3093. EXPECT_CALL(canvas, onDrawImage2(_, _, _, _, _)).Times(0);
  3094. DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params);
  3095. }
  3096. }
  3097. TEST(PaintOpBufferTest, DrawSkottieOpRasterWithNullImages) {
  3098. scoped_refptr<SkottieWrapper> skottie =
  3099. CreateSkottieFromString(kLottieDataWith2Assets);
  3100. SkRect skottie_rect = SkRect::MakeWH(100, 100);
  3101. SkottieFrameDataMap images_in = GetNullImagesForSkottie(*skottie, /*t=*/0.1f);
  3102. ASSERT_FALSE(images_in.empty());
  3103. DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.1, images_in,
  3104. SkottieColorMap(), SkottieTextPropertyValueMap());
  3105. PlaybackParams playback_params(/*image_provider=*/nullptr);
  3106. {
  3107. NiceMock<MockCanvas> canvas;
  3108. EXPECT_CALL(canvas, onDrawImage2(_, _, _, _, _)).Times(0);
  3109. DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params);
  3110. }
  3111. }
  3112. TEST(PaintOpBufferTest, DrawSkottieOpRasterWithoutImageProvider) {
  3113. scoped_refptr<SkottieWrapper> skottie =
  3114. CreateSkottieFromString(kLottieDataWith2Assets);
  3115. SkRect skottie_rect = SkRect::MakeWH(100, 100);
  3116. SkottieFrameDataMap images_in = GetTestImagesForSkottie(
  3117. *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.1f);
  3118. ASSERT_FALSE(images_in.empty());
  3119. DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.1, images_in,
  3120. SkottieColorMap(), SkottieTextPropertyValueMap());
  3121. PlaybackParams playback_params(/*image_provider=*/nullptr);
  3122. {
  3123. NiceMock<MockCanvas> canvas;
  3124. // Do not over-assert. Ultimately it is up to Skottie's implementation how
  3125. // many "draw image" calls are made, and what the arguments are. But it's
  3126. // fair to say that it has to make at least one "draw image" call for a
  3127. // frame in the animation that renders one of the assets.
  3128. EXPECT_CALL(canvas, onDrawImage2(NotNull(), _, _, _, _)).Times(AtLeast(1));
  3129. DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params);
  3130. }
  3131. }
  3132. TEST(PaintOpBufferTest, DrawSkottieOpRasterWithImageProvider) {
  3133. scoped_refptr<SkottieWrapper> skottie =
  3134. CreateSkottieFromString(kLottieDataWith2Assets);
  3135. SkRect skottie_rect = SkRect::MakeWH(100, 100);
  3136. std::vector<SkSize> src_rect_offset = {SkSize::Make(2.0f, 2.0f),
  3137. SkSize::Make(3.0f, 3.0f)};
  3138. std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f),
  3139. SkSize::Make(0.3f, 0.3f)};
  3140. std::vector<PaintFlags::FilterQuality> quality = {
  3141. PaintFlags::FilterQuality::kHigh, PaintFlags::FilterQuality::kMedium};
  3142. MockImageProvider image_provider(src_rect_offset, scale_adjustment, quality);
  3143. PlaybackParams playback_params(&image_provider);
  3144. ASSERT_TRUE(image_provider.decoded_images().empty());
  3145. {
  3146. SkottieFrameDataMap images_in = GetTestImagesForSkottie(
  3147. *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.25f);
  3148. ASSERT_THAT(images_in, Contains(Key(HashSkottieResourceId("image_0"))));
  3149. DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.25, images_in,
  3150. SkottieColorMap(), SkottieTextPropertyValueMap());
  3151. NiceMock<MockCanvas> canvas;
  3152. EXPECT_CALL(canvas, onDrawImage2(NotNull(), _, _, _, _)).Times(AtLeast(1));
  3153. DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params);
  3154. ASSERT_EQ(image_provider.decoded_images().size(), 1u);
  3155. EXPECT_THAT(image_provider.decoded_images(),
  3156. Contains(MatchesPaintImage(
  3157. images_in.at(HashSkottieResourceId("image_0")).image)));
  3158. }
  3159. {
  3160. SkottieFrameDataMap images_in = GetTestImagesForSkottie(
  3161. *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.75f);
  3162. ASSERT_THAT(images_in, Contains(Key(HashSkottieResourceId("image_1"))));
  3163. DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.75, images_in,
  3164. SkottieColorMap(), SkottieTextPropertyValueMap());
  3165. NiceMock<MockCanvas> canvas;
  3166. EXPECT_CALL(canvas, onDrawImage2(NotNull(), _, _, _, _)).Times(AtLeast(1));
  3167. DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params);
  3168. ASSERT_EQ(image_provider.decoded_images().size(), 2u);
  3169. EXPECT_THAT(image_provider.decoded_images(),
  3170. Contains(MatchesPaintImage(
  3171. images_in.at(HashSkottieResourceId("image_1")).image)));
  3172. }
  3173. }
  3174. TEST(PaintOpBufferTest, DiscardableImagesTrackingSkottieOpNoImages) {
  3175. PaintOpBuffer buffer;
  3176. buffer.push<DrawSkottieOp>(
  3177. CreateSkottie(gfx::Size(100, 100), /*duration_secs=*/1),
  3178. /*dst=*/SkRect::MakeWH(100, 100), /*t=*/0.1f, SkottieFrameDataMap(),
  3179. SkottieColorMap(), SkottieTextPropertyValueMap());
  3180. EXPECT_FALSE(buffer.HasDiscardableImages());
  3181. }
  3182. TEST(PaintOpBufferTest, DiscardableImagesTrackingSkottieOpWithImages) {
  3183. PaintOpBuffer buffer;
  3184. scoped_refptr<SkottieWrapper> skottie =
  3185. CreateSkottieFromString(kLottieDataWith2Assets);
  3186. SkRect skottie_rect = SkRect::MakeWH(100, 100);
  3187. SkottieFrameDataMap images_in = GetTestImagesForSkottie(
  3188. *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.1f);
  3189. ASSERT_FALSE(images_in.empty());
  3190. buffer.push<DrawSkottieOp>(skottie, skottie_rect, /*t=*/0.1f, images_in,
  3191. SkottieColorMap(), SkottieTextPropertyValueMap());
  3192. EXPECT_TRUE(buffer.HasDiscardableImages());
  3193. }
  3194. TEST(PaintOpBufferTest, OpHasDiscardableImagesSkottieOpNoImages) {
  3195. DrawSkottieOp op(CreateSkottie(gfx::Size(100, 100), /*duration_secs=*/1),
  3196. /*dst=*/SkRect::MakeWH(100, 100), /*t=*/0.1f,
  3197. SkottieFrameDataMap(), SkottieColorMap(),
  3198. SkottieTextPropertyValueMap());
  3199. EXPECT_FALSE(PaintOp::OpHasDiscardableImages(&op));
  3200. }
  3201. TEST(PaintOpBufferTest, OpHasDiscardableImagesSkottieOpWithImages) {
  3202. scoped_refptr<SkottieWrapper> skottie =
  3203. CreateSkottieFromString(kLottieDataWith2Assets);
  3204. SkRect skottie_rect = SkRect::MakeWH(100, 100);
  3205. SkottieFrameDataMap images_in = GetTestImagesForSkottie(
  3206. *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.1f);
  3207. ASSERT_FALSE(images_in.empty());
  3208. DrawSkottieOp op(skottie, skottie_rect, /*t=*/0.1f, images_in,
  3209. SkottieColorMap(), SkottieTextPropertyValueMap());
  3210. EXPECT_TRUE(PaintOp::OpHasDiscardableImages(&op));
  3211. }
  3212. #endif // BUILDFLAG(SKIA_SUPPORT_SKOTTIE)
  3213. TEST(PaintOpBufferTest, CustomData) {
  3214. // Basic tests: size, move, comparison.
  3215. {
  3216. PaintOpBuffer buffer;
  3217. EXPECT_EQ(buffer.size(), 0u);
  3218. EXPECT_EQ(buffer.bytes_used(), sizeof(PaintOpBuffer));
  3219. buffer.push<CustomDataOp>(1234u);
  3220. EXPECT_EQ(buffer.size(), 1u);
  3221. EXPECT_GT(buffer.bytes_used(),
  3222. sizeof(PaintOpBuffer) + sizeof(CustomDataOp));
  3223. PaintOpBuffer new_buffer = std::move(buffer);
  3224. EXPECT_EQ(buffer.size(), 0u);
  3225. EXPECT_EQ(new_buffer.size(), 1u);
  3226. EXPECT_EQ(new_buffer.GetFirstOp()->GetType(), PaintOpType::CustomData);
  3227. PaintOpBuffer buffer2;
  3228. buffer2.push<CustomDataOp>(1234u);
  3229. EXPECT_TRUE(*new_buffer.GetFirstOp() == *buffer2.GetFirstOp());
  3230. }
  3231. // Push and verify.
  3232. {
  3233. PaintOpBuffer buffer;
  3234. buffer.push<SaveOp>();
  3235. buffer.push<CustomDataOp>(0xFFFFFFFF);
  3236. buffer.push<RestoreOp>();
  3237. EXPECT_EQ(buffer.size(), 3u);
  3238. PaintOpBuffer::Iterator iter(&buffer);
  3239. ASSERT_EQ(iter->GetType(), PaintOpType::Save);
  3240. ++iter;
  3241. ASSERT_EQ(iter->GetType(), PaintOpType::CustomData);
  3242. ++iter;
  3243. ASSERT_EQ(iter->GetType(), PaintOpType::Restore);
  3244. ++iter;
  3245. }
  3246. // Playback.
  3247. {
  3248. PaintOpBuffer buffer;
  3249. buffer.push<CustomDataOp>(9999u);
  3250. testing::StrictMock<MockCanvas> canvas;
  3251. EXPECT_CALL(canvas, onCustomCallback(&canvas, 9999)).Times(1);
  3252. buffer.Playback(&canvas, PlaybackParams(nullptr, SkM44(),
  3253. base::BindRepeating(
  3254. &MockCanvas::onCustomCallback,
  3255. base::Unretained(&canvas))));
  3256. }
  3257. }
  3258. TEST(PaintOpBufferTest, SecurityConstrainedImageSerialization) {
  3259. auto image = CreateDiscardablePaintImage(gfx::Size(10, 10));
  3260. sk_sp<PaintFilter> filter = sk_make_sp<ImagePaintFilter>(
  3261. image, SkRect::MakeWH(10, 10), SkRect::MakeWH(10, 10),
  3262. PaintFlags::FilterQuality::kLow);
  3263. const bool enable_security_constraints = true;
  3264. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3265. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3266. PaintOpBuffer::PaintOpAlign)));
  3267. TestOptionsProvider options_provider;
  3268. PaintOpWriter writer(memory.get(), PaintOpBuffer::kInitialBufferSize,
  3269. options_provider.serialize_options(),
  3270. enable_security_constraints);
  3271. writer.Write(filter.get(), SkM44());
  3272. sk_sp<PaintFilter> out_filter;
  3273. PaintOpReader reader(memory.get(), writer.size(),
  3274. options_provider.deserialize_options(),
  3275. enable_security_constraints);
  3276. reader.Read(&out_filter);
  3277. EXPECT_TRUE(*filter == *out_filter);
  3278. }
  3279. TEST(PaintOpBufferTest, DrawImageRectSerializeScaledImages) {
  3280. auto buffer = sk_make_sp<PaintOpBuffer>();
  3281. // scales: x dimension = x0.25, y dimension = x5
  3282. // translations here are arbitrary
  3283. SkRect src = SkRect::MakeXYWH(3, 4, 20, 6);
  3284. SkRect dst = SkRect::MakeXYWH(20, 38, 5, 30);
  3285. // Adjust transform matrix so that order of operations for src->dst is
  3286. // confirmed to be applied before the canvas's transform.
  3287. buffer->push<TranslateOp>(.5f * dst.centerX(), 2.f * dst.centerY());
  3288. buffer->push<RotateOp>(90.f);
  3289. buffer->push<TranslateOp>(-.5f * dst.centerX(), -2.f * dst.centerY());
  3290. buffer->push<ScaleOp>(0.5f, 2.0f);
  3291. buffer->push<DrawImageRectOp>(CreateDiscardablePaintImage(gfx::Size(32, 16)),
  3292. src, dst, SkCanvas::kStrict_SrcRectConstraint);
  3293. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3294. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3295. PaintOpBuffer::PaintOpAlign)));
  3296. TestOptionsProvider options_provider;
  3297. SimpleBufferSerializer serializer(memory.get(),
  3298. PaintOpBuffer::kInitialBufferSize,
  3299. options_provider.serialize_options());
  3300. serializer.Serialize(buffer.get());
  3301. ASSERT_EQ(options_provider.decoded_images().size(), 1u);
  3302. auto scale = options_provider.decoded_images().at(0).scale();
  3303. EXPECT_EQ(scale.width(), 0.5f * 0.25f);
  3304. EXPECT_EQ(scale.height(), 2.0f * 5.0f);
  3305. }
  3306. TEST(PaintOpBufferTest, RecordShadersSerializeScaledImages) {
  3307. auto record_buffer = sk_make_sp<PaintOpBuffer>();
  3308. record_buffer->push<DrawImageOp>(
  3309. CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f);
  3310. auto shader = PaintShader::MakePaintRecord(
  3311. record_buffer, SkRect::MakeWH(10.f, 10.f), SkTileMode::kRepeat,
  3312. SkTileMode::kRepeat, nullptr);
  3313. shader->set_has_animated_images(true);
  3314. auto buffer = sk_make_sp<PaintOpBuffer>();
  3315. buffer->push<ScaleOp>(0.5f, 0.8f);
  3316. PaintFlags flags;
  3317. flags.setShader(shader);
  3318. buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags);
  3319. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3320. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3321. PaintOpBuffer::PaintOpAlign)));
  3322. TestOptionsProvider options_provider;
  3323. SimpleBufferSerializer serializer(memory.get(),
  3324. PaintOpBuffer::kInitialBufferSize,
  3325. options_provider.serialize_options());
  3326. serializer.Serialize(buffer.get());
  3327. ASSERT_EQ(options_provider.decoded_images().size(), 1u);
  3328. auto scale = options_provider.decoded_images().at(0).scale();
  3329. EXPECT_EQ(scale.width(), 0.5f);
  3330. EXPECT_EQ(scale.height(), 0.8f);
  3331. }
  3332. TEST(PaintOpBufferTest, RecordShadersCached) {
  3333. auto record_buffer = sk_make_sp<PaintOpBuffer>();
  3334. record_buffer->push<DrawImageOp>(
  3335. CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f);
  3336. auto shader = PaintShader::MakePaintRecord(
  3337. record_buffer, SkRect::MakeWH(10.f, 10.f), SkTileMode::kRepeat,
  3338. SkTileMode::kRepeat, nullptr);
  3339. shader->set_has_animated_images(false);
  3340. auto shader_id = shader->paint_record_shader_id();
  3341. TestOptionsProvider options_provider;
  3342. auto* transfer_cache = options_provider.transfer_cache_helper();
  3343. // Generate serialized |memory|.
  3344. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3345. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3346. PaintOpBuffer::PaintOpAlign)));
  3347. size_t memory_written = 0;
  3348. {
  3349. auto buffer = sk_make_sp<PaintOpBuffer>();
  3350. PaintFlags flags;
  3351. flags.setShader(shader);
  3352. buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags);
  3353. SimpleBufferSerializer serializer(memory.get(),
  3354. PaintOpBuffer::kInitialBufferSize,
  3355. options_provider.serialize_options());
  3356. serializer.Serialize(buffer.get());
  3357. memory_written = serializer.written();
  3358. }
  3359. // Generate serialized |memory_scaled|, which is the same pob, but with
  3360. // a scale factor.
  3361. std::unique_ptr<char, base::AlignedFreeDeleter> memory_scaled(
  3362. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3363. PaintOpBuffer::PaintOpAlign)));
  3364. size_t memory_scaled_written = 0;
  3365. {
  3366. auto buffer = sk_make_sp<PaintOpBuffer>();
  3367. PaintFlags flags;
  3368. flags.setShader(shader);
  3369. // This buffer has an additional scale op.
  3370. buffer->push<ScaleOp>(2.0f, 3.7f);
  3371. buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags);
  3372. SimpleBufferSerializer serializer(memory_scaled.get(),
  3373. PaintOpBuffer::kInitialBufferSize,
  3374. options_provider.serialize_options());
  3375. serializer.Serialize(buffer.get());
  3376. memory_scaled_written = serializer.written();
  3377. }
  3378. // Hold onto records so PaintShader pointer comparisons are valid.
  3379. sk_sp<PaintRecord> records[5];
  3380. SkPicture* last_shader = nullptr;
  3381. std::vector<uint8_t> scratch_buffer;
  3382. PaintOp::DeserializeOptions deserialize_options(
  3383. transfer_cache, options_provider.service_paint_cache(),
  3384. options_provider.strike_client(), &scratch_buffer, true, nullptr);
  3385. // Several deserialization test cases:
  3386. // (0) deserialize once, verify cached is the same as deserialized version
  3387. // (1) deserialize again, verify shader gets reused
  3388. // (2) change scale, verify shader is new
  3389. // (3) sanity check, same new scale + same new colorspace, shader is reused.
  3390. for (size_t i = 0; i < 4; ++i) {
  3391. if (i < 2) {
  3392. records[i] = PaintOpBuffer::MakeFromMemory(memory.get(), memory_written,
  3393. deserialize_options);
  3394. } else {
  3395. records[i] = PaintOpBuffer::MakeFromMemory(
  3396. memory_scaled.get(), memory_scaled_written, deserialize_options);
  3397. }
  3398. auto* entry =
  3399. transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>(shader_id);
  3400. ASSERT_TRUE(entry);
  3401. if (i < 2)
  3402. EXPECT_EQ(records[i]->size(), 1u);
  3403. else
  3404. EXPECT_EQ(records[i]->size(), 2u);
  3405. for (auto* base_op : PaintOpBuffer::Iterator(records[i].get())) {
  3406. if (base_op->GetType() != PaintOpType::DrawRect)
  3407. continue;
  3408. auto* op = static_cast<const DrawRectOp*>(base_op);
  3409. // In every case, the shader in the op should get cached for future
  3410. // use.
  3411. auto* op_skshader = op->flags.getShader()->sk_cached_picture_.get();
  3412. EXPECT_EQ(op_skshader, entry->shader()->sk_cached_picture_.get());
  3413. switch (i) {
  3414. case 0:
  3415. // Nothing to check.
  3416. break;
  3417. case 1:
  3418. EXPECT_EQ(op_skshader, last_shader);
  3419. break;
  3420. case 2:
  3421. EXPECT_NE(op_skshader, last_shader);
  3422. break;
  3423. case 3:
  3424. EXPECT_EQ(op_skshader, last_shader);
  3425. break;
  3426. }
  3427. last_shader = op_skshader;
  3428. }
  3429. }
  3430. }
  3431. TEST(PaintOpBufferTest, RecordShadersCachedSize) {
  3432. auto record_buffer = sk_make_sp<PaintOpBuffer>();
  3433. size_t estimated_image_size = 30 * 30 * 4;
  3434. auto image = CreateBitmapImage(gfx::Size(30, 30));
  3435. record_buffer->push<DrawImageOp>(image, 0.f, 0.f);
  3436. auto shader = PaintShader::MakePaintRecord(
  3437. record_buffer, SkRect::MakeWH(10.f, 10.f), SkTileMode::kRepeat,
  3438. SkTileMode::kRepeat, nullptr);
  3439. shader->set_has_animated_images(false);
  3440. auto shader_id = shader->paint_record_shader_id();
  3441. TestOptionsProvider options_provider;
  3442. auto* transfer_cache = options_provider.transfer_cache_helper();
  3443. // Generate serialized |memory|.
  3444. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3445. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3446. PaintOpBuffer::PaintOpAlign)));
  3447. auto buffer = sk_make_sp<PaintOpBuffer>();
  3448. PaintFlags flags;
  3449. flags.setShader(shader);
  3450. buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags);
  3451. SimpleBufferSerializer serializer(memory.get(),
  3452. PaintOpBuffer::kInitialBufferSize,
  3453. options_provider.serialize_options());
  3454. options_provider.context_supports_distance_field_text();
  3455. serializer.Serialize(buffer.get());
  3456. std::vector<uint8_t> scratch_buffer;
  3457. PaintOp::DeserializeOptions deserialize_options(
  3458. transfer_cache, options_provider.service_paint_cache(),
  3459. options_provider.strike_client(), &scratch_buffer, true, nullptr);
  3460. auto record = PaintOpBuffer::MakeFromMemory(
  3461. memory.get(), serializer.written(), deserialize_options);
  3462. auto* shader_entry =
  3463. transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>(shader_id);
  3464. ASSERT_TRUE(shader_entry);
  3465. // The size of the shader in the cache should be bigger than both the record
  3466. // and the image. Exact numbers not used here to not overfit this test.
  3467. size_t shader_size = shader_entry->CachedSize();
  3468. EXPECT_GT(estimated_image_size, serializer.written());
  3469. EXPECT_GT(shader_size, estimated_image_size);
  3470. }
  3471. TEST(PaintOpBufferTest, RecordFilterSerializeScaledImages) {
  3472. auto record_buffer = sk_make_sp<PaintOpBuffer>();
  3473. record_buffer->push<DrawImageOp>(
  3474. CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f);
  3475. auto filter =
  3476. sk_make_sp<RecordPaintFilter>(record_buffer, SkRect::MakeWH(10.f, 10.f));
  3477. auto buffer = sk_make_sp<PaintOpBuffer>();
  3478. buffer->push<ScaleOp>(0.5f, 0.8f);
  3479. PaintFlags flags;
  3480. flags.setImageFilter(filter);
  3481. buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags);
  3482. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3483. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3484. PaintOpBuffer::PaintOpAlign)));
  3485. TestOptionsProvider options_provider;
  3486. SimpleBufferSerializer serializer(memory.get(),
  3487. PaintOpBuffer::kInitialBufferSize,
  3488. options_provider.serialize_options());
  3489. serializer.Serialize(buffer.get());
  3490. ASSERT_EQ(options_provider.decoded_images().size(), 1u);
  3491. auto scale = options_provider.decoded_images().at(0).scale();
  3492. EXPECT_EQ(scale.width(), 0.5f);
  3493. EXPECT_EQ(scale.height(), 0.8f);
  3494. }
  3495. TEST(PaintOpBufferTest, TotalOpCount) {
  3496. auto record_buffer = sk_make_sp<PaintOpBuffer>();
  3497. auto sub_record_buffer = sk_make_sp<PaintOpBuffer>();
  3498. auto sub_sub_record_buffer = sk_make_sp<PaintOpBuffer>();
  3499. PushDrawRectOps(sub_sub_record_buffer.get());
  3500. PushDrawRectOps(sub_record_buffer.get());
  3501. PushDrawRectOps(record_buffer.get());
  3502. sub_record_buffer->push<DrawRecordOp>(sub_sub_record_buffer);
  3503. record_buffer->push<DrawRecordOp>(sub_record_buffer);
  3504. size_t len = std::min(test_rects.size(), test_flags.size());
  3505. EXPECT_EQ(len, sub_sub_record_buffer->total_op_count());
  3506. EXPECT_EQ(2 * len + 1, sub_record_buffer->total_op_count());
  3507. EXPECT_EQ(3 * len + 2, record_buffer->total_op_count());
  3508. }
  3509. TEST(PaintOpBufferTest, NullImages) {
  3510. PaintOpBuffer buffer;
  3511. buffer.push<DrawImageOp>(PaintImage(), 0.f, 0.f);
  3512. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3513. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3514. PaintOpBuffer::PaintOpAlign)));
  3515. TestOptionsProvider options_provider;
  3516. SimpleBufferSerializer serializer(memory.get(),
  3517. PaintOpBuffer::kInitialBufferSize,
  3518. options_provider.serialize_options());
  3519. serializer.Serialize(&buffer);
  3520. ASSERT_TRUE(serializer.valid());
  3521. ASSERT_GT(serializer.written(), 0u);
  3522. auto deserialized_buffer =
  3523. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  3524. options_provider.deserialize_options());
  3525. ASSERT_TRUE(deserialized_buffer);
  3526. ASSERT_EQ(deserialized_buffer->size(), 1u);
  3527. ASSERT_EQ(deserialized_buffer->GetFirstOp()->GetType(),
  3528. PaintOpType::DrawImage);
  3529. }
  3530. TEST(PaintOpBufferTest, HasDrawOpsAndHasDrawTextOps) {
  3531. auto buffer1 = sk_make_sp<PaintOpBuffer>();
  3532. EXPECT_FALSE(buffer1->has_draw_ops());
  3533. EXPECT_FALSE(buffer1->has_draw_text_ops());
  3534. buffer1->push<DrawRectOp>(SkRect::MakeWH(3, 4), PaintFlags());
  3535. PushDrawRectOps(buffer1.get());
  3536. EXPECT_TRUE(buffer1->has_draw_ops());
  3537. EXPECT_FALSE(buffer1->has_draw_text_ops());
  3538. auto buffer2 = sk_make_sp<PaintOpBuffer>();
  3539. EXPECT_FALSE(buffer2->has_draw_ops());
  3540. EXPECT_FALSE(buffer2->has_draw_text_ops());
  3541. buffer2->push<DrawRecordOp>(std::move(buffer1));
  3542. EXPECT_TRUE(buffer2->has_draw_ops());
  3543. EXPECT_FALSE(buffer2->has_draw_text_ops());
  3544. buffer2->push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()),
  3545. 0.0f, 0.0f, PaintFlags());
  3546. EXPECT_TRUE(buffer2->has_draw_ops());
  3547. EXPECT_TRUE(buffer2->has_draw_text_ops());
  3548. buffer2->push<DrawRectOp>(SkRect::MakeWH(4, 5), PaintFlags());
  3549. EXPECT_TRUE(buffer2->has_draw_ops());
  3550. EXPECT_TRUE(buffer2->has_draw_text_ops());
  3551. auto buffer3 = sk_make_sp<PaintOpBuffer>();
  3552. EXPECT_FALSE(buffer3->has_draw_text_ops());
  3553. EXPECT_FALSE(buffer3->has_draw_ops());
  3554. buffer3->push<DrawRecordOp>(std::move(buffer2));
  3555. EXPECT_TRUE(buffer3->has_draw_ops());
  3556. EXPECT_TRUE(buffer3->has_draw_text_ops());
  3557. }
  3558. TEST(PaintOpBufferTest, HasEffectsPreventingLCDTextForSaveLayerAlpha) {
  3559. auto buffer1 = sk_make_sp<PaintOpBuffer>();
  3560. EXPECT_FALSE(buffer1->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3561. buffer1->push<DrawRectOp>(SkRect::MakeWH(3, 4), PaintFlags());
  3562. EXPECT_FALSE(buffer1->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3563. auto buffer2 = sk_make_sp<PaintOpBuffer>();
  3564. EXPECT_FALSE(buffer2->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3565. buffer2->push<DrawRecordOp>(std::move(buffer1));
  3566. EXPECT_FALSE(buffer2->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3567. buffer2->push<SaveLayerOp>(nullptr, nullptr);
  3568. EXPECT_TRUE(buffer2->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3569. buffer2->push<DrawRectOp>(SkRect::MakeWH(4, 5), PaintFlags());
  3570. EXPECT_TRUE(buffer2->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3571. auto buffer3 = sk_make_sp<PaintOpBuffer>();
  3572. EXPECT_FALSE(buffer3->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3573. buffer3->push<DrawRecordOp>(std::move(buffer2));
  3574. EXPECT_TRUE(buffer3->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3575. }
  3576. TEST(PaintOpBufferTest, NeedsAdditionalInvalidationForLCDText) {
  3577. auto buffer1 = sk_make_sp<PaintOpBuffer>();
  3578. buffer1->push<SaveLayerAlphaOp>(nullptr, 0.4f);
  3579. EXPECT_FALSE(buffer1->has_draw_text_ops());
  3580. EXPECT_TRUE(buffer1->has_save_layer_alpha_ops());
  3581. EXPECT_FALSE(buffer1->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3582. auto buffer2 = sk_make_sp<PaintOpBuffer>();
  3583. buffer2->push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()),
  3584. 0.0f, 0.0f, PaintFlags());
  3585. buffer2->push<SaveLayerOp>(nullptr, nullptr);
  3586. EXPECT_TRUE(buffer2->has_draw_ops());
  3587. EXPECT_FALSE(buffer2->has_save_layer_alpha_ops());
  3588. EXPECT_TRUE(buffer2->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3589. // Neither buffer has effects preventing lcd text for SaveLayerAlpha.
  3590. EXPECT_FALSE(buffer1->NeedsAdditionalInvalidationForLCDText(*buffer2));
  3591. EXPECT_FALSE(buffer2->NeedsAdditionalInvalidationForLCDText(*buffer1));
  3592. {
  3593. auto buffer3 = sk_make_sp<PaintOpBuffer>();
  3594. buffer3->push<DrawRecordOp>(buffer2);
  3595. EXPECT_TRUE(
  3596. buffer3->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3597. // Neither buffer has both DrawText and SaveLayerAlpha.
  3598. EXPECT_FALSE(buffer1->NeedsAdditionalInvalidationForLCDText(*buffer3));
  3599. EXPECT_FALSE(buffer3->NeedsAdditionalInvalidationForLCDText(*buffer1));
  3600. EXPECT_FALSE(buffer2->NeedsAdditionalInvalidationForLCDText(*buffer3));
  3601. EXPECT_FALSE(buffer3->NeedsAdditionalInvalidationForLCDText(*buffer2));
  3602. }
  3603. {
  3604. buffer1->push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()),
  3605. 0.0f, 0.0f, PaintFlags());
  3606. EXPECT_TRUE(buffer1->has_draw_text_ops());
  3607. EXPECT_TRUE(buffer1->has_save_layer_alpha_ops());
  3608. EXPECT_FALSE(
  3609. buffer1->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3610. auto buffer3 = sk_make_sp<PaintOpBuffer>();
  3611. buffer3->push<DrawRecordOp>(buffer1);
  3612. buffer3->push<DrawRecordOp>(buffer2);
  3613. EXPECT_TRUE(buffer3->has_draw_text_ops());
  3614. EXPECT_TRUE(buffer3->has_save_layer_alpha_ops());
  3615. EXPECT_TRUE(
  3616. buffer3->has_effects_preventing_lcd_text_for_save_layer_alpha());
  3617. // Both have DrawText and SaveLayerAlpha, and have different
  3618. // has_effects_preventing_lcd_text_for_save_layer_alpha().
  3619. EXPECT_TRUE(buffer1->NeedsAdditionalInvalidationForLCDText(*buffer3));
  3620. EXPECT_TRUE(buffer3->NeedsAdditionalInvalidationForLCDText(*buffer1));
  3621. EXPECT_FALSE(buffer3->NeedsAdditionalInvalidationForLCDText(*buffer3));
  3622. }
  3623. }
  3624. // A regression test for crbug.com/1195276. Ensure that PlaybackParams works
  3625. // with SetMatrix operations.
  3626. TEST(PaintOpBufferTest, SetMatrixOpWithNonIdentityPlaybackParams) {
  3627. for (const auto& original_ctm : test_matrices) {
  3628. for (const auto& matrix : test_matrices) {
  3629. SkCanvas device(0, 0);
  3630. SkCanvas* canvas = &device;
  3631. PlaybackParams params(nullptr, original_ctm);
  3632. SetMatrixOp op(matrix);
  3633. SetMatrixOp::Raster(&op, canvas, params);
  3634. EXPECT_TRUE(AnnotateOp::AreSkM44sEqual(canvas->getLocalToDevice(),
  3635. SkM44(original_ctm, matrix)));
  3636. }
  3637. }
  3638. }
  3639. TEST(PaintOpBufferTest, PathCaching) {
  3640. SkPath path;
  3641. PaintFlags flags;
  3642. // Grow path large enough to trigger caching
  3643. path.moveTo(0, 0);
  3644. for (int x = 1; x < 100; ++x)
  3645. path.lineTo(x, x % 1);
  3646. TestOptionsProvider options_provider;
  3647. std::unique_ptr<char, base::AlignedFreeDeleter> memory(
  3648. static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
  3649. PaintOpBuffer::PaintOpAlign)));
  3650. auto buffer = sk_make_sp<PaintOpBuffer>();
  3651. buffer->push<DrawPathOp>(path, flags, UsePaintCache::kEnabled);
  3652. SimpleBufferSerializer serializer(memory.get(),
  3653. PaintOpBuffer::kInitialBufferSize,
  3654. options_provider.serialize_options());
  3655. serializer.Serialize(buffer.get());
  3656. EXPECT_TRUE(options_provider.client_paint_cache()->Get(
  3657. PaintCacheDataType::kPath, path.getGenerationID()));
  3658. auto deserialized_buffer =
  3659. PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
  3660. options_provider.deserialize_options());
  3661. ASSERT_TRUE(deserialized_buffer);
  3662. ASSERT_EQ(deserialized_buffer->size(), 1u);
  3663. ASSERT_EQ(deserialized_buffer->GetFirstOp()->GetType(),
  3664. PaintOpType::DrawPath);
  3665. SkPath cached_path;
  3666. EXPECT_TRUE(options_provider.service_paint_cache()->GetPath(
  3667. path.getGenerationID(), &cached_path));
  3668. }
  3669. } // namespace cc