| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2015 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #ifndef GrTInstanceBatch_DEFINED | |
| 9 #define GrTInstanceBatch_DEFINED | |
| 10 | |
| 11 #include "GrVertexBatch.h" | |
| 12 | |
| 13 #include "GrBatchFlushState.h" | |
| 14 | |
| 15 /** | |
| 16 * GrTInstanceBatch is an optional template to help with writing batches | |
| 17 * To use this template, The 'Impl' must define the following statics: | |
| 18 * A Geometry struct | |
| 19 * | |
| 20 * static const int kVertsPerInstance | |
| 21 * static const int kIndicesPerInstance | |
| 22 * | |
| 23 * const char* Name() | |
| 24 * | |
| 25 * void InvariantOutputCoverage(GrInitInvariantOutput* out) | |
| 26 * | |
| 27 * void SetBounds(const Geometry& seedGeometry, SkRect* outBounds) | |
| 28 * | |
| 29 * void UpdateBoundsAfterAppend(const Geometry& lastGeometry, SkRect* curren
tBounds) | |
| 30 * | |
| 31 * bool CanCombine(const Geometry& mine, const Geometry& theirs, | |
| 32 * const GrXPOverridesForBatch&) | |
| 33 * | |
| 34 * const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry, | |
| 35 * const GrXPOverridesForBatch& override
s) | |
| 36 * | |
| 37 * const GrBuffer* GetIndexBuffer(GrResourceProvider*) | |
| 38 * | |
| 39 * Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo, | |
| 40 * const GrXPOverridesForBatch& overrides) | |
| 41 */ | |
| 42 template <typename Impl> | |
| 43 class GrTInstanceBatch : public GrVertexBatch { | |
| 44 public: | |
| 45 DEFINE_BATCH_CLASS_ID | |
| 46 | |
| 47 typedef typename Impl::Geometry Geometry; | |
| 48 | |
| 49 static GrTInstanceBatch* Create() { return new GrTInstanceBatch; } | |
| 50 | |
| 51 const char* name() const override { return Impl::Name(); } | |
| 52 | |
| 53 SkString dumpInfo() const override { | |
| 54 SkString str; | |
| 55 str.appendf("# batched: %d\n", fGeoData.count()); | |
| 56 for (int i = 0; i < fGeoData.count(); ++i) { | |
| 57 str.append(Impl::DumpInfo(fGeoData[i], i)); | |
| 58 } | |
| 59 str.append(INHERITED::dumpInfo()); | |
| 60 return str; | |
| 61 } | |
| 62 | |
| 63 void computePipelineOptimizations(GrInitInvariantOutput* color, | |
| 64 GrInitInvariantOutput* coverage, | |
| 65 GrBatchToXPOverrides* overrides) const ove
rride { | |
| 66 // When this is called on a batch, there is only one geometry bundle | |
| 67 color->setKnownFourComponents(fGeoData[0].fColor); | |
| 68 Impl::InitInvariantOutputCoverage(coverage); | |
| 69 } | |
| 70 | |
| 71 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | |
| 72 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | |
| 73 fOverrides = overrides; | |
| 74 } | |
| 75 | |
| 76 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 77 | |
| 78 // After seeding, the client should call init() so the Batch can initialize
itself | |
| 79 void init() { | |
| 80 const Geometry& geo = fGeoData[0]; | |
| 81 Impl::SetBounds(geo, &fBounds); | |
| 82 } | |
| 83 | |
| 84 void updateBoundsAfterAppend() { | |
| 85 const Geometry& geo = fGeoData.back(); | |
| 86 Impl::UpdateBoundsAfterAppend(geo, &fBounds); | |
| 87 } | |
| 88 | |
| 89 private: | |
| 90 GrTInstanceBatch() : INHERITED(ClassID()) {} | |
| 91 | |
| 92 void onPrepareDraws(Target* target) const override { | |
| 93 sk_sp<GrGeometryProcessor> gp(Impl::MakeGP(this->seedGeometry(), fOverri
des)); | |
| 94 if (!gp) { | |
| 95 SkDebugf("Couldn't create GrGeometryProcessor\n"); | |
| 96 return; | |
| 97 } | |
| 98 | |
| 99 size_t vertexStride = gp->getVertexStride(); | |
| 100 int instanceCount = fGeoData.count(); | |
| 101 | |
| 102 SkAutoTUnref<const GrBuffer> indexBuffer( | |
| 103 Impl::GetIndexBuffer(target->resourceProvider())); | |
| 104 InstancedHelper helper; | |
| 105 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexS
tride, | |
| 106 indexBuffer, Impl::kVertsPerInstance, | |
| 107 Impl::kIndicesPerInstance, instanceCount); | |
| 108 if (!vertices || !indexBuffer) { | |
| 109 SkDebugf("Could not allocate vertices\n"); | |
| 110 return; | |
| 111 } | |
| 112 | |
| 113 for (int i = 0; i < instanceCount; i++) { | |
| 114 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + | |
| 115 i * Impl::kVertsPerInstance * vertexStride; | |
| 116 Impl::Tesselate(verts, vertexStride, fGeoData[i], fOverrides); | |
| 117 } | |
| 118 helper.recordDraw(target, gp.get()); | |
| 119 } | |
| 120 | |
| 121 const Geometry& seedGeometry() const { return fGeoData[0]; } | |
| 122 | |
| 123 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | |
| 124 GrTInstanceBatch* that = t->cast<GrTInstanceBatch>(); | |
| 125 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | |
| 126 that->bounds(), caps)) { | |
| 127 return false; | |
| 128 } | |
| 129 | |
| 130 if (!Impl::CanCombine(this->seedGeometry(), that->seedGeometry(), fOverr
ides)) { | |
| 131 return false; | |
| 132 } | |
| 133 | |
| 134 // In the event of two batches, one who can tweak, one who cannot, we ju
st fall back to | |
| 135 // not tweaking | |
| 136 if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakA
lphaForCoverage()) { | |
| 137 fOverrides = that->fOverrides; | |
| 138 } | |
| 139 | |
| 140 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | |
| 141 this->joinBounds(that->bounds()); | |
| 142 return true; | |
| 143 } | |
| 144 | |
| 145 GrXPOverridesForBatch fOverrides; | |
| 146 SkSTArray<1, Geometry, true> fGeoData; | |
| 147 | |
| 148 typedef GrVertexBatch INHERITED; | |
| 149 }; | |
| 150 | |
| 151 #endif | |
| OLD | NEW |