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