1eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips/* 2eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * Copyright 2017 Google Inc. 3eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * 4eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * Use of this source code is governed by a BSD-style license that can be 5eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * found in the LICENSE file. 6eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips */ 7eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 8eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "Test.h" 9eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 10eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#if SK_SUPPORT_GPU 11eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 12a5cb781c17c09e01655defd0a84b431996b6a015Greg Daniel#include "GrBackendSemaphore.h" 13eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "GrClip.h" 14eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "GrContextPriv.h" 15eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "GrDefaultGeoProcFactory.h" 16fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton#include "GrOnFlushResourceProvider.h" 17eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "GrRenderTargetContextPriv.h" 18eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "GrResourceProvider.h" 19eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "GrQuad.h" 20eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "effects/GrSimpleTextureEffect.h" 219a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon#include "ops/GrSimpleMeshDrawOpHelper.h" 22eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 239a03642ad2fce5805642783f68078a0a6bf03554Brian Salomonnamespace { 24eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips// This is a simplified mesh drawing op that can be used in the atlas generation test. 25eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips// Please see AtlasedRectOp below. 269a03642ad2fce5805642783f68078a0a6bf03554Brian Salomonclass NonAARectOp : public GrMeshDrawOp { 279a03642ad2fce5805642783f68078a0a6bf03554Brian Salomonprotected: 289a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon using Helper = GrSimpleMeshDrawOpHelper; 299a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon 30eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipspublic: 31eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips DEFINE_OP_CLASS_ID 32eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips const char* name() const override { return "NonAARectOp"; } 33eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 34eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // This creates an instance of a simple non-AA solid color rect-drawing Op 359a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkRect& r) { 369a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon return Helper::FactoryHelper<NonAARectOp>(std::move(paint), r, nullptr, ClassID()); 37eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 38eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 39eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // This creates an instance of a simple non-AA textured rect-drawing Op 409a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkRect& r, const SkRect& local) { 419a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon return Helper::FactoryHelper<NonAARectOp>(std::move(paint), r, &local, ClassID()); 42eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 43eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 44eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColor color() const { return fColor; } 45eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 469a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon NonAARectOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkRect& r, 479a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon const SkRect* localRect, int32_t classID) 489a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon : INHERITED(classID) 499a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon , fColor(color) 509a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon , fHasLocalRect(SkToBool(localRect)) 519a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon , fRect(r) 529a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon , fHelper(helperArgs, GrAAType::kNone) { 539a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon if (fHasLocalRect) { 549a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon fLocalQuad.set(*localRect); 559a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon } 56eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Choose some conservative values for aa bloat and zero area. 57eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips this->setBounds(r, HasAABloat::kYes, IsZeroArea::kYes); 58eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 59eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 609a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } 619a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon 629a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip*) override { 639a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon // Set the color to unknown because the subclass may change the color later. 649a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon GrProcessorAnalysisColor gpColor; 659a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon gpColor.setToUnknown(); 669a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon // We ignore the clip so pass this rather than the GrAppliedClip param. 679a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon static GrAppliedClip kNoClip; 689a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon return fHelper.xpRequiresDstTexture(caps, &kNoClip, GrProcessorAnalysisCoverage::kNone, 699a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon &gpColor); 70eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 71eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 729a03642ad2fce5805642783f68078a0a6bf03554Brian Salomonprotected: 73eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColor fColor; 74eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bool fHasLocalRect; 75eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrQuad fLocalQuad; 76eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkRect fRect; 77eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 78eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsprivate: 79eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; } 80eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 81eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void onPrepareDraws(Target* target) const override { 82eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips using namespace GrDefaultGeoProcFactory; 83eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 84eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // The vertex attrib order is always pos, color, local coords. 85eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips static const int kColorOffset = sizeof(SkPoint); 86eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor); 87eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 88eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrGeometryProcessor> gp = 89eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, 90eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips Coverage::kSolid_Type, 91eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fHasLocalRect ? LocalCoords::kHasExplicit_Type 92eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips : LocalCoords::kUnused_Type, 93eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkMatrix::I()); 94eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (!gp) { 95eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkDebugf("Couldn't create GrGeometryProcessor for GrAtlasedOp\n"); 96eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return; 97eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 98eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 99eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips size_t vertexStride = gp->getVertexStride(); 100eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 101eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(fHasLocalRect 102eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) 103eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips : vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr)); 104eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 105eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips const GrBuffer* indexBuffer; 106eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips int firstIndex; 107eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips uint16_t* indices = target->makeIndexSpace(6, &indexBuffer, &firstIndex); 108eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (!indices) { 109eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkDebugf("Indices could not be allocated for GrAtlasedOp.\n"); 110eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return; 111eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 112eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 113eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips const GrBuffer* vertexBuffer; 114eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips int firstVertex; 115eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void* vertices = target->makeVertexSpace(vertexStride, 4, &vertexBuffer, &firstVertex); 116eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (!vertices) { 117eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkDebugf("Vertices could not be allocated for GrAtlasedOp.\n"); 118eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return; 119eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 120eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 121eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Setup indices 122eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips indices[0] = 0; 123eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips indices[1] = 1; 124eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips indices[2] = 2; 125eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips indices[3] = 0; 126eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips indices[4] = 2; 127eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips indices[5] = 3; 128eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 129eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Setup positions 130eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkPoint* position = (SkPoint*) vertices; 131eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips position->setRectFan(fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom, vertexStride); 132eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 133eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Setup vertex colors 134eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColor* color = (GrColor*)((intptr_t)vertices + kColorOffset); 135eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < 4; ++i) { 136eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips *color = fColor; 137eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips color = (GrColor*)((intptr_t)color + vertexStride); 138eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 139eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 140eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Setup local coords 141eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (fHasLocalRect) { 142eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkPoint* coords = (SkPoint*)((intptr_t) vertices + kLocalOffset); 143eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < 4; i++) { 144eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips *coords = fLocalQuad.point(i); 145eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips coords = (SkPoint*)((intptr_t) coords + vertexStride); 146eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 147eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 148eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 1493809bab7ed344ad140346c38e149dabf10bd525fChris Dalton GrMesh mesh(GrPrimitiveType::kTriangles); 150114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton mesh.setIndexed(indexBuffer, 6, firstIndex, 0, 3); 151114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton mesh.setVertexData(vertexBuffer, firstVertex); 152eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 1539a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon target->draw(gp.get(), fHelper.makePipeline(target), mesh); 154eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 155eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 1569a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon Helper fHelper; 1579a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon 1589a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon typedef GrMeshDrawOp INHERITED; 159eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips}; 160eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 1619a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon} // anonymous namespace 1629a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon 163eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#ifdef SK_DEBUG 164eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "SkImageEncoder.h" 165eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "sk_tool_utils.h" 166eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 167eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsstatic void save_bm(const SkBitmap& bm, const char name[]) { 168eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bool result = sk_tool_utils::EncodeImageToFile(name, bm, SkEncodedImageFormat::kPNG, 100); 169eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(result); 170eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips} 171eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#endif 172eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 1739a03642ad2fce5805642783f68078a0a6bf03554Brian Salomonstatic constexpr SkRect kEmptyRect = SkRect::MakeEmpty(); 1749a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon 1759a03642ad2fce5805642783f68078a0a6bf03554Brian Salomonnamespace { 1769a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon 177eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips/* 178eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * Atlased ops just draw themselves as textured rects with the texture pixels being 179eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * pulled out of the atlas. Their color is based on their ID. 180eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips */ 181eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsclass AtlasedRectOp final : public NonAARectOp { 182eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipspublic: 183eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips DEFINE_OP_CLASS_ID 184eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 185eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips ~AtlasedRectOp() override { 186eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fID = -1; 187eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 188eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 189eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips const char* name() const override { return "AtlasedRectOp"; } 190eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 191eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips int id() const { return fID; } 192eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 1939a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon static std::unique_ptr<AtlasedRectOp> Make(GrPaint&& paint, const SkRect& r, int id) { 1949a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon GrDrawOp* op = Helper::FactoryHelper<AtlasedRectOp>(std::move(paint), r, id).release(); 1959a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon return std::unique_ptr<AtlasedRectOp>(static_cast<AtlasedRectOp*>(op)); 1969a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon } 1979a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon 1989a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon // We set the initial color of the NonAARectOp based on the ID. 1999a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon // Note that we force creation of a NonAARectOp that has local coords in anticipation of 2009a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon // pulling from the atlas. 2019a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon AtlasedRectOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkRect& r, int id) 2029a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon : INHERITED(helperArgs, kColors[id], r, &kEmptyRect, ClassID()) 2039a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon , fID(id) 2049a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon , fNext(nullptr) { 2059a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon SkASSERT(fID < kMaxIDs); 206eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 207eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 208eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void setColor(GrColor color) { fColor = color; } 209eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void setLocalRect(const SkRect& localRect) { 210eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(fHasLocalRect); // This should've been created to anticipate this 211eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fLocalQuad.set(localRect); 212eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 213eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 214eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips AtlasedRectOp* next() const { return fNext; } 215eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void setNext(AtlasedRectOp* next) { 216eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fNext = next; 217eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 218eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 219eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsprivate: 220eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 221eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips static const int kMaxIDs = 9; 222eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips static const SkColor kColors[kMaxIDs]; 223eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 224eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips int fID; 225eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // The Atlased ops have an internal singly-linked list of ops that land in the same opList 226eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips AtlasedRectOp* fNext; 227eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 228eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips typedef NonAARectOp INHERITED; 229eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips}; 230eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 2319a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon} // anonymous namespace 2329a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon 233eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsconst GrColor AtlasedRectOp::kColors[kMaxIDs] = { 234eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(255, 0, 0, 255), 235eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(0, 255, 0, 255), 236eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(0, 0, 255, 255), 237eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(0, 255, 255, 255), 238eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(255, 0, 255, 255), 239eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(255, 255, 0, 255), 240eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(0, 0, 0, 255), 241eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(128, 128, 128, 255), 242eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrColorPackRGBA(255, 255, 255, 255) 243eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips}; 244eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 245eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsstatic const int kDrawnTileSize = 16; 246eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 247eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips/* 248eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * Rather than performing any rect packing, this atlaser just lays out constant-sized 249eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * tiles in an Nx1 row 250eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips */ 251eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsstatic const int kAtlasTileSize = 2; 252eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 253eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips/* 254eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * This class aggregates the op information required for atlasing 255eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips */ 256fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Daltonclass AtlasObject final : public GrOnFlushCallbackObject { 257eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipspublic: 258eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips AtlasObject() : fDone(false) { } 259eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 260eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips ~AtlasObject() override { 261eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(fDone); 262eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 263eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 264eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void markAsDone() { 265eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fDone = true; 266eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 267eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 268eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Insert the new op in an internal singly-linked list for 'opListID' 269eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void addOp(uint32_t opListID, AtlasedRectOp* op) { 270eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips LinkedListHeader* header = nullptr; 271eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < fOps.count(); ++i) { 272eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (opListID == fOps[i].fID) { 273eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips header = &(fOps[i]); 274eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 275eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 276eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 277eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (!header) { 278eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fOps.push({opListID, nullptr}); 279eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips header = &(fOps[fOps.count()-1]); 280eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 281eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 282eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips op->setNext(header->fHead); 283eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips header->fHead = op; 284eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 285eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 286eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // For the time being we need to pre-allocate the atlas. 287eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void setAtlasDest(sk_sp<GrTextureProxy> atlasDest) { 288eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fAtlasDest = atlasDest; 289eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 290eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 291eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void saveRTC(sk_sp<GrRenderTargetContext> rtc) { 292eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(!fRTC); 293eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fRTC = rtc; 294eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 295eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 296eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#ifdef SK_DEBUG 297eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void saveAtlasToDisk() { 298eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkBitmap readBack; 299eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips readBack.allocN32Pixels(fRTC->width(), fRTC->height()); 300eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 301eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bool result = fRTC->readPixels(readBack.info(), 302eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips readBack.getPixels(), readBack.rowBytes(), 0, 0); 303eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(result); 304eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips save_bm(readBack, "atlas-real.png"); 305eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 306eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#endif 307eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 308eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips /* 309eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * This callback back creates the atlas and updates the AtlasedRectOps to read from it 310eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips */ 311fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton void preFlush(GrOnFlushResourceProvider* resourceProvider, 312eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips const uint32_t* opListIDs, int numOpListIDs, 313eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkTArray<sk_sp<GrRenderTargetContext>>* results) override { 314eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(!results->count()); 315eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 316eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Until MDB is landed we will most-likely only have one opList. 317eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkTDArray<LinkedListHeader*> lists; 318eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < numOpListIDs; ++i) { 319eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (LinkedListHeader* list = this->getList(opListIDs[i])) { 320eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips lists.push(list); 321eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 322eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 323eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 324eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (!lists.count()) { 325eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return; // nothing to atlas 326eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 327eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 328eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // TODO: right now we have to pre-allocate the atlas bc the TextureSamplers need a 329eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // hard GrTexture 330eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#if 0 331eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrSurfaceDesc desc; 332eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fFlags = kRenderTarget_GrSurfaceFlag; 333eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fWidth = this->numOps() * kAtlasTileSize; 334eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fHeight = kAtlasTileSize; 335eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fConfig = kRGBA_8888_GrPixelConfig; 336eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 337eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrRenderTargetContext> rtc = resourceProvider->makeRenderTargetContext(desc, 338eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips nullptr, 339eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips nullptr); 340eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#else 341eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // At this point all the GrAtlasedOp's should have lined up to read from 'atlasDest' and 342eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // there should either be two writes to clear it or no writes. 343eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(9 == fAtlasDest->getPendingReadCnt_TestOnly()); 344eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(2 == fAtlasDest->getPendingWriteCnt_TestOnly() || 345eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 0 == fAtlasDest->getPendingWriteCnt_TestOnly()); 346eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrRenderTargetContext> rtc = resourceProvider->makeRenderTargetContext( 347eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips fAtlasDest, 348eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips nullptr, nullptr); 349eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#endif 350eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 351eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips rtc->clear(nullptr, 0xFFFFFFFF, true); // clear the atlas 352eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 353eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips int blocksInAtlas = 0; 354eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < lists.count(); ++i) { 355eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (AtlasedRectOp* op = lists[i]->fHead; op; op = op->next()) { 356eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkIRect r = SkIRect::MakeXYWH(blocksInAtlas*kAtlasTileSize, 0, 357eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips kAtlasTileSize, kAtlasTileSize); 358eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 359eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // For now, we avoid the resource buffer issues and just use clears 360eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#if 1 361eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips rtc->clear(&r, op->color(), false); 362eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#else 363eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrPaint paint; 3649a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon paint.setColor4f(GrColor4f::FromGrColor(op->color())); 3659a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon std::unique_ptr<GrDrawOp> drawOp(NonAARectOp::Make(std::move(paint), 3669a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon SkRect::Make(r))); 3679a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon rtc->priv().testingOnly_addDrawOp(std::move(drawOp)); 368eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#endif 369eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips blocksInAtlas++; 370eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 371eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Set the atlased Op's color to white (so we know we're not using it for 372eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // the final draw). 373eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips op->setColor(0xFFFFFFFF); 374eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 375eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Set the atlased Op's localRect to point to where it landed in the atlas 376eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips op->setLocalRect(SkRect::Make(r)); 377eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 378eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // TODO: we also need to set the op's GrSuperDeferredSimpleTextureEffect to point 379eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // to the rtc's proxy! 380eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 381eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 382eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // We've updated all these ops and we certainly don't want to process them again 383eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips this->clearOpsFor(lists[i]); 384eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 385eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 386eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Hide a ref to the RTC in AtlasData so we can check on it later 387eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips this->saveRTC(rtc); 388eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 389eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips results->push_back(std::move(rtc)); 390eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 391eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 392eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsprivate: 393eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips typedef struct { 394eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips uint32_t fID; 395eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips AtlasedRectOp* fHead; 396eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } LinkedListHeader; 397eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 398eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips LinkedListHeader* getList(uint32_t opListID) { 399eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < fOps.count(); ++i) { 400eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (opListID == fOps[i].fID) { 401eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return &(fOps[i]); 402eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 403eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 404eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return nullptr; 405eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 406eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 407eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips void clearOpsFor(LinkedListHeader* header) { 408eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // The AtlasedRectOps have yet to execute (and this class doesn't own them) so just 409eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // forget about them in the laziest way possible. 410eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips header->fHead = nullptr; 411eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips header->fID = 0; // invalid opList ID 412eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 413eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 414eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Each opList containing AtlasedRectOps gets its own internal singly-linked list 415eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkTDArray<LinkedListHeader> fOps; 416eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 417eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // The RTC used to create the atlas 418eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrRenderTargetContext> fRTC; 419eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 420eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // For the time being we need to pre-allocate the atlas bc the TextureSamplers require 421eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // a GrTexture 422eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrTextureProxy> fAtlasDest; 423eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 424eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Set to true when the testing harness expects this object to be no longer used 425eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bool fDone; 426eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips}; 427eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 428eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips// This creates an off-screen rendertarget whose ops which eventually pull from the atlas. 429eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsstatic sk_sp<GrTextureProxy> make_upstream_image(GrContext* context, AtlasObject* object, int start, 430eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrTextureProxy> fakeAtlas) { 431dd3b3f41829d32d7eaf3eb4903570d49c2ba9ff8Robert Phillips sk_sp<GrRenderTargetContext> rtc(context->makeDeferredRenderTargetContext( 432dd3b3f41829d32d7eaf3eb4903570d49c2ba9ff8Robert Phillips SkBackingFit::kApprox, 433eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 3*kDrawnTileSize, 434eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips kDrawnTileSize, 435eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips kRGBA_8888_GrPixelConfig, 436eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips nullptr)); 437eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 438eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips rtc->clear(nullptr, GrColorPackRGBA(255, 0, 0, 255), true); 439eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 440eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < 3; ++i) { 441eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkRect r = SkRect::MakeXYWH(i*kDrawnTileSize, 0, kDrawnTileSize, kDrawnTileSize); 442eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 443eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // TODO: here is the blocker for deferring creation of the atlas. The TextureSamplers 444eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // created here currently require a hard GrTexture. 445fbcef6eb8abad142daf45418516550f7635b4a52Robert Phillips sk_sp<GrFragmentProcessor> fp = GrSimpleTextureEffect::Make(fakeAtlas, 446eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips nullptr, SkMatrix::I()); 447eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrPaint paint; 448eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips paint.addColorFragmentProcessor(std::move(fp)); 449eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 4509a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon std::unique_ptr<AtlasedRectOp> op(AtlasedRectOp::Make(std::move(paint), r, start + i)); 451eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 452eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips AtlasedRectOp* sparePtr = op.get(); 453eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 4549a03642ad2fce5805642783f68078a0a6bf03554Brian Salomon uint32_t opListID = rtc->priv().testingOnly_addDrawOp(std::move(op)); 455eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 456eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips object->addOp(opListID, sparePtr); 457eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 458eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 459eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return rtc->asTextureProxyRef(); 460eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips} 461eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 462eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips// Enable this if you want to debug the final draws w/o having the atlasCallback create the 463eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips// atlas 464eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#if 0 465eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#include "SkGrPriv.h" 466eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 467eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipssk_sp<GrTextureProxy> pre_create_atlas(GrContext* context) { 468eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkBitmap bm; 469eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.allocN32Pixels(18, 2, true); 470eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorRED, SkIRect::MakeXYWH(0, 0, 2, 2)); 471eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorGREEN, SkIRect::MakeXYWH(2, 0, 2, 2)); 472eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorBLUE, SkIRect::MakeXYWH(4, 0, 2, 2)); 473eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorCYAN, SkIRect::MakeXYWH(6, 0, 2, 2)); 474eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorMAGENTA, SkIRect::MakeXYWH(8, 0, 2, 2)); 475eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorYELLOW, SkIRect::MakeXYWH(10, 0, 2, 2)); 476eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorBLACK, SkIRect::MakeXYWH(12, 0, 2, 2)); 477eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorGRAY, SkIRect::MakeXYWH(14, 0, 2, 2)); 478eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.erase(SK_ColorWHITE, SkIRect::MakeXYWH(16, 0, 2, 2)); 479eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 480eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#if 1 481eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips save_bm(bm, "atlas-fake.png"); 482eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#endif 483eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 484eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bm.info(), *context->caps()); 485eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fFlags |= kRenderTarget_GrSurfaceFlag; 486eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 487eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrSurfaceProxy> tmp = GrSurfaceProxy::MakeDeferred(*context->caps(), 488eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips context->textureProvider(), 489eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc, SkBudgeted::kYes, 490eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips bm.getPixels(), bm.rowBytes()); 491eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 492eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return sk_ref_sp(tmp->asTextureProxy()); 493eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips} 494eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#else 495eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips// TODO: this is unfortunate and must be removed. We want the atlas to be created later. 496eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipssk_sp<GrTextureProxy> pre_create_atlas(GrContext* context) { 497eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrSurfaceDesc desc; 498eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fFlags = kRenderTarget_GrSurfaceFlag; 499eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fConfig = kSkia8888_GrPixelConfig; 500eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fOrigin = kBottomLeft_GrSurfaceOrigin; 501eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fWidth = 32; 502eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc.fHeight = 16; 503eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrSurfaceProxy> atlasDest = GrSurfaceProxy::MakeDeferred( 504eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips context->resourceProvider(), 505eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips desc, SkBackingFit::kExact, 506eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkBudgeted::kYes, 507eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrResourceProvider::kNoPendingIO_Flag); 508eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return sk_ref_sp(atlasDest->asTextureProxy()); 509eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips} 510eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#endif 511eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 512eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillipsstatic void test_color(skiatest::Reporter* reporter, const SkBitmap& bm, int x, SkColor expected) { 513eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkColor readback = bm.getColor(x, kDrawnTileSize/2); 514eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips REPORTER_ASSERT(reporter, expected == readback); 515eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (expected != readback) { 516eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkDebugf("Color mismatch: %x %x\n", expected, readback); 517eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 518eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips} 519eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 520eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips/* 521eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * For the atlasing test we make a DAG that looks like: 522eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * 523eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * RT1 with ops: 0,1,2 RT2 with ops: 3,4,5 RT3 with ops: 6,7,8 524eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * \ / 525eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * \ / 526eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * RT4 527eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * We then flush RT4 and expect only ops 0-5 to be atlased together. 528eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * Each op is just a solid colored rect so both the atlas and the final image should appear as: 529eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * R G B C M Y 530eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * with the atlas having width = 6*kAtlasTileSize and height = kAtlasTileSize. 531eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * 532eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * Note: until MDB lands, the atlas will actually have width= 9*kAtlasTileSize and look like: 533eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips * R G B C M Y K Grey White 534eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips */ 535fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris DaltonDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(OnFlushCallbackTest, reporter, ctxInfo) { 536eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips static const int kNumProxies = 3; 537eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 538eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrContext* context = ctxInfo.grContext(); 539eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 540eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips if (context->caps()->useDrawInsteadOfClear()) { 541eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // TODO: fix the buffer issues so this can run on all devices 542eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips return; 543eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 544eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 545fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton AtlasObject object; 546eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 547eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // For now (until we add a GrSuperDeferredSimpleTextureEffect), we create the final atlas 548eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // proxy ahead of time. 549eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrTextureProxy> atlasDest = pre_create_atlas(context); 550eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 551fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton object.setAtlasDest(atlasDest); 552eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 553fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton context->contextPriv().addOnFlushCallbackObject(&object); 554eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 555eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips sk_sp<GrTextureProxy> proxies[kNumProxies]; 556eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < kNumProxies; ++i) { 557fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton proxies[i] = make_upstream_image(context, &object, i*3, atlasDest); 558eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 559eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 560eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips static const int kFinalWidth = 6*kDrawnTileSize; 561eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips static const int kFinalHeight = kDrawnTileSize; 562eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 563dd3b3f41829d32d7eaf3eb4903570d49c2ba9ff8Robert Phillips sk_sp<GrRenderTargetContext> rtc(context->makeDeferredRenderTargetContext( 564dd3b3f41829d32d7eaf3eb4903570d49c2ba9ff8Robert Phillips SkBackingFit::kApprox, 565eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips kFinalWidth, 566eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips kFinalHeight, 567eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips kRGBA_8888_GrPixelConfig, 568eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips nullptr)); 569eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 570eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips rtc->clear(nullptr, 0xFFFFFFFF, true); 571eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 572eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips // Note that this doesn't include the third texture proxy 573eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips for (int i = 0; i < kNumProxies-1; ++i) { 574eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkRect r = SkRect::MakeXYWH(i*3*kDrawnTileSize, 0, 3*kDrawnTileSize, kDrawnTileSize); 575eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 576eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkMatrix t = SkMatrix::MakeTrans(-i*3*kDrawnTileSize, 0); 577eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 578eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips GrPaint paint; 579fbcef6eb8abad142daf45418516550f7635b4a52Robert Phillips sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(std::move(proxies[i]), 580eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips nullptr, t)); 581eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 582eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips paint.addColorFragmentProcessor(std::move(fp)); 583eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 584eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), r); 585eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips } 586eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 587a5cb781c17c09e01655defd0a84b431996b6a015Greg Daniel rtc->prepareForExternalIO(0, nullptr); 588eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 589eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkBitmap readBack; 590eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips readBack.allocN32Pixels(kFinalWidth, kFinalHeight); 591eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 592eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkDEBUGCODE(bool result =) rtc->readPixels(readBack.info(), readBack.getPixels(), 593eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips readBack.rowBytes(), 0, 0); 594eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips SkASSERT(result); 595eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 596fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton context->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(&object); 597fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton 598fe199b7d512a7cfc56deaaa134260e1d47a1e7e0Chris Dalton object.markAsDone(); 599eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 600eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#if 0 601eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips save_bm(readBack, "atlas-final-image.png"); 602eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips data.saveAtlasToDisk(); 603eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#endif 604eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 605eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips int x = kDrawnTileSize/2; 606eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips test_color(reporter, readBack, x, SK_ColorRED); 607eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips x += kDrawnTileSize; 608eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips test_color(reporter, readBack, x, SK_ColorGREEN); 609eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips x += kDrawnTileSize; 610eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips test_color(reporter, readBack, x, SK_ColorBLUE); 611eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips x += kDrawnTileSize; 612eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips test_color(reporter, readBack, x, SK_ColorCYAN); 613eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips x += kDrawnTileSize; 614eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips test_color(reporter, readBack, x, SK_ColorMAGENTA); 615eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips x += kDrawnTileSize; 616eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips test_color(reporter, readBack, x, SK_ColorYELLOW); 617eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips} 618eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips 619eb35f4dfaa10b9d751abbc9a1406456eb3b1649dRobert Phillips#endif 620