Index: src/gpu/instanced/InstancedRendering.cpp |
diff --git a/src/gpu/instanced/InstancedRendering.cpp b/src/gpu/instanced/InstancedRendering.cpp |
deleted file mode 100644 |
index 165bff494b3fa0ab1f241c844ec59afb8b582da9..0000000000000000000000000000000000000000 |
--- a/src/gpu/instanced/InstancedRendering.cpp |
+++ /dev/null |
@@ -1,474 +0,0 @@ |
-/* |
- * Copyright 2016 Google Inc. |
- * |
- * Use of this source code is governed by a BSD-style license that can be |
- * found in the LICENSE file. |
- */ |
- |
-#include "InstancedRendering.h" |
- |
-#include "GrBatchFlushState.h" |
-#include "GrPipeline.h" |
-#include "GrResourceProvider.h" |
-#include "instanced/InstanceProcessor.h" |
- |
-namespace gr_instanced { |
- |
-InstancedRendering::InstancedRendering(GrGpu* gpu, AntialiasMode lastSupportedAAMode, |
- bool canRenderToFloat) |
- : fGpu(SkRef(gpu)), |
- fLastSupportedAAMode(lastSupportedAAMode), |
- fCanRenderToFloat(canRenderToFloat), |
- fState(State::kRecordingDraws), |
- fDrawPool(1024 * sizeof(Batch::Draw), 1024 * sizeof(Batch::Draw)) { |
-} |
- |
-GrDrawBatch* InstancedRendering::recordRect(const SkRect& rect, const SkMatrix& viewMatrix, |
- GrColor color, bool antialias, |
- const GrInstancedPipelineInfo& info, bool* useHWAA) { |
- return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect, antialias, info, |
- useHWAA); |
-} |
- |
-GrDrawBatch* InstancedRendering::recordRect(const SkRect& rect, const SkMatrix& viewMatrix, |
- GrColor color, const SkRect& localRect, bool antialias, |
- const GrInstancedPipelineInfo& info, bool* useHWAA) { |
- return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, localRect, antialias, info, |
- useHWAA); |
-} |
- |
-GrDrawBatch* InstancedRendering::recordRect(const SkRect& rect, const SkMatrix& viewMatrix, |
- GrColor color, const SkMatrix& localMatrix, |
- bool antialias, const GrInstancedPipelineInfo& info, |
- bool* useHWAA) { |
- if (localMatrix.hasPerspective()) { |
- return nullptr; // Perspective is not yet supported in the local matrix. |
- } |
- if (Batch* batch = this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect, antialias, |
- info, useHWAA)) { |
- batch->getSingleInstance().fInfo |= kLocalMatrix_InfoFlag; |
- batch->appendParamsTexel(localMatrix.getScaleX(), localMatrix.getSkewX(), |
- localMatrix.getTranslateX()); |
- batch->appendParamsTexel(localMatrix.getSkewY(), localMatrix.getScaleY(), |
- localMatrix.getTranslateY()); |
- batch->fInfo.fHasLocalMatrix = true; |
- return batch; |
- } |
- return nullptr; |
-} |
- |
-GrDrawBatch* InstancedRendering::recordOval(const SkRect& oval, const SkMatrix& viewMatrix, |
- GrColor color, bool antialias, |
- const GrInstancedPipelineInfo& info, bool* useHWAA) { |
- return this->recordShape(ShapeType::kOval, oval, viewMatrix, color, oval, antialias, info, |
- useHWAA); |
-} |
- |
-GrDrawBatch* InstancedRendering::recordRRect(const SkRRect& rrect, const SkMatrix& viewMatrix, |
- GrColor color, bool antialias, |
- const GrInstancedPipelineInfo& info, bool* useHWAA) { |
- if (Batch* batch = this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix, color, |
- rrect.rect(), antialias, info, useHWAA)) { |
- batch->appendRRectParams(rrect); |
- return batch; |
- } |
- return nullptr; |
-} |
- |
-GrDrawBatch* InstancedRendering::recordDRRect(const SkRRect& outer, const SkRRect& inner, |
- const SkMatrix& viewMatrix, GrColor color, |
- bool antialias, const GrInstancedPipelineInfo& info, |
- bool* useHWAA) { |
- if (inner.getType() > SkRRect::kSimple_Type) { |
- return nullptr; // Complex inner round rects are not yet supported. |
- } |
- if (SkRRect::kEmpty_Type == inner.getType()) { |
- return this->recordRRect(outer, viewMatrix, color, antialias, info, useHWAA); |
- } |
- if (Batch* batch = this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix, color, |
- outer.rect(), antialias, info, useHWAA)) { |
- batch->appendRRectParams(outer); |
- ShapeType innerShapeType = GetRRectShapeType(inner); |
- batch->fInfo.fInnerShapeTypes |= GetShapeFlag(innerShapeType); |
- batch->getSingleInstance().fInfo |= ((int)innerShapeType << kInnerShapeType_InfoBit); |
- batch->appendParamsTexel(inner.rect().asScalars(), 4); |
- batch->appendRRectParams(inner); |
- return batch; |
- } |
- return nullptr; |
-} |
- |
-InstancedRendering::Batch* InstancedRendering::recordShape(ShapeType type, const SkRect& bounds, |
- const SkMatrix& viewMatrix, |
- GrColor color, const SkRect& localRect, |
- bool antialias, |
- const GrInstancedPipelineInfo& info, |
- bool* useHWAA) { |
- SkASSERT(State::kRecordingDraws == fState); |
- |
- if (info.fIsRenderingToFloat && !fCanRenderToFloat) { |
- return nullptr; |
- } |
- |
- AntialiasMode antialiasMode; |
- if (!this->selectAntialiasMode(viewMatrix, antialias, info, useHWAA, &antialiasMode)) { |
- return nullptr; |
- } |
- |
- Batch* batch = this->createBatch(); |
- batch->fInfo.fAntialiasMode = antialiasMode; |
- batch->fInfo.fShapeTypes = GetShapeFlag(type); |
- batch->fInfo.fCannotDiscard = !info.fCanDiscard; |
- |
- Instance& instance = batch->getSingleInstance(); |
- instance.fInfo = (int)type << kShapeType_InfoBit; |
- |
- // The instanced shape renderer draws rectangles of [-1, -1, +1, +1], so we find the matrix that |
- // will map this rectangle to the same device coordinates as "viewMatrix * bounds". |
- float sx = 0.5f * bounds.width(); |
- float sy = 0.5f * bounds.height(); |
- float tx = sx + bounds.fLeft; |
- float ty = sy + bounds.fTop; |
- if (!viewMatrix.hasPerspective()) { |
- float* m = instance.fShapeMatrix2x3; |
- m[0] = viewMatrix.getScaleX() * sx; |
- m[1] = viewMatrix.getSkewX() * sy; |
- m[2] = viewMatrix.getTranslateX() + |
- viewMatrix.getScaleX() * tx + viewMatrix.getSkewX() * ty; |
- |
- m[3] = viewMatrix.getSkewY() * sx; |
- m[4] = viewMatrix.getScaleY() * sy; |
- m[5] = viewMatrix.getTranslateY() + |
- viewMatrix.getSkewY() * tx + viewMatrix.getScaleY() * ty; |
- |
- // Since 'm' is a 2x3 matrix that maps the rect [-1, +1] into the shape's device-space quad, |
- // it's quite simple to find the bounding rectangle: |
- float devBoundsHalfWidth = fabsf(m[0]) + fabsf(m[1]); |
- float devBoundsHalfHeight = fabsf(m[3]) + fabsf(m[4]); |
- batch->fBounds.fLeft = m[2] - devBoundsHalfWidth; |
- batch->fBounds.fRight = m[2] + devBoundsHalfWidth; |
- batch->fBounds.fTop = m[5] - devBoundsHalfHeight; |
- batch->fBounds.fBottom = m[5] + devBoundsHalfHeight; |
- |
- // TODO: Is this worth the CPU overhead? |
- batch->fInfo.fNonSquare = |
- fabsf(devBoundsHalfHeight - devBoundsHalfWidth) > 0.5f || // Early out. |
- fabs(m[0] * m[3] + m[1] * m[4]) > 1e-3f || // Skew? |
- fabs(m[0] * m[0] + m[1] * m[1] - m[3] * m[3] - m[4] * m[4]) > 1e-2f; // Diff. lengths? |
- } else { |
- SkMatrix shapeMatrix(viewMatrix); |
- shapeMatrix.preTranslate(tx, ty); |
- shapeMatrix.preScale(sx, sy); |
- instance.fInfo |= kPerspective_InfoFlag; |
- |
- float* m = instance.fShapeMatrix2x3; |
- m[0] = SkScalarToFloat(shapeMatrix.getScaleX()); |
- m[1] = SkScalarToFloat(shapeMatrix.getSkewX()); |
- m[2] = SkScalarToFloat(shapeMatrix.getTranslateX()); |
- m[3] = SkScalarToFloat(shapeMatrix.getSkewY()); |
- m[4] = SkScalarToFloat(shapeMatrix.getScaleY()); |
- m[5] = SkScalarToFloat(shapeMatrix.getTranslateY()); |
- |
- // Send the perspective column as a param. |
- batch->appendParamsTexel(shapeMatrix[SkMatrix::kMPersp0], shapeMatrix[SkMatrix::kMPersp1], |
- shapeMatrix[SkMatrix::kMPersp2]); |
- batch->fInfo.fHasPerspective = true; |
- |
- viewMatrix.mapRect(&batch->fBounds, bounds); |
- |
- batch->fInfo.fNonSquare = true; |
- } |
- |
- instance.fColor = color; |
- |
- const float* rectAsFloats = localRect.asScalars(); // Ensure SkScalar == float. |
- memcpy(&instance.fLocalRect, rectAsFloats, 4 * sizeof(float)); |
- |
- return batch; |
-} |
- |
-inline bool InstancedRendering::selectAntialiasMode(const SkMatrix& viewMatrix, bool antialias, |
- const GrInstancedPipelineInfo& info, |
- bool* useHWAA, AntialiasMode* antialiasMode) { |
- SkASSERT(!info.fColorDisabled || info.fDrawingShapeToStencil); |
- SkASSERT(!info.fIsMixedSampled || info.fIsMultisampled); |
- |
- if (!info.fIsMultisampled || fGpu->caps()->multisampleDisableSupport()) { |
- SkASSERT(fLastSupportedAAMode >= AntialiasMode::kCoverage); |
- if (!antialias) { |
- if (info.fDrawingShapeToStencil && !info.fCanDiscard) { |
- // We can't draw to the stencil buffer without discard (or sample mask if MSAA). |
- return false; |
- } |
- *antialiasMode = AntialiasMode::kNone; |
- *useHWAA = false; |
- return true; |
- } |
- |
- if (info.canUseCoverageAA() && viewMatrix.preservesRightAngles()) { |
- *antialiasMode = AntialiasMode::kCoverage; |
- *useHWAA = false; |
- return true; |
- } |
- } |
- |
- if (info.fIsMultisampled && fLastSupportedAAMode >= AntialiasMode::kMSAA) { |
- if (!info.fIsMixedSampled || info.fColorDisabled) { |
- *antialiasMode = AntialiasMode::kMSAA; |
- *useHWAA = true; |
- return true; |
- } |
- if (fLastSupportedAAMode >= AntialiasMode::kMixedSamples) { |
- *antialiasMode = AntialiasMode::kMixedSamples; |
- *useHWAA = true; |
- return true; |
- } |
- } |
- |
- return false; |
-} |
- |
-InstancedRendering::Batch::Batch(uint32_t classID, InstancedRendering* ir) |
- : INHERITED(classID), |
- fInstancedRendering(ir), |
- fIsTracked(false), |
- fNumDraws(1), |
- fNumChangesInGeometry(0) { |
- fHeadDraw = fTailDraw = (Draw*)fInstancedRendering->fDrawPool.allocate(sizeof(Draw)); |
-#ifdef SK_DEBUG |
- fHeadDraw->fGeometry = {-1, 0}; |
-#endif |
- fHeadDraw->fNext = nullptr; |
-} |
- |
-InstancedRendering::Batch::~Batch() { |
- if (fIsTracked) { |
- fInstancedRendering->fTrackedBatches.remove(this); |
- } |
- |
- Draw* draw = fHeadDraw; |
- while (draw) { |
- Draw* next = draw->fNext; |
- fInstancedRendering->fDrawPool.release(draw); |
- draw = next; |
- } |
-} |
- |
-void InstancedRendering::Batch::appendRRectParams(const SkRRect& rrect) { |
- SkASSERT(!fIsTracked); |
- switch (rrect.getType()) { |
- case SkRRect::kSimple_Type: { |
- const SkVector& radii = rrect.getSimpleRadii(); |
- this->appendParamsTexel(radii.x(), radii.y(), rrect.width(), rrect.height()); |
- return; |
- } |
- case SkRRect::kNinePatch_Type: { |
- float twoOverW = 2 / rrect.width(); |
- float twoOverH = 2 / rrect.height(); |
- const SkVector& radiiTL = rrect.radii(SkRRect::kUpperLeft_Corner); |
- const SkVector& radiiBR = rrect.radii(SkRRect::kLowerRight_Corner); |
- this->appendParamsTexel(radiiTL.x() * twoOverW, radiiBR.x() * twoOverW, |
- radiiTL.y() * twoOverH, radiiBR.y() * twoOverH); |
- return; |
- } |
- case SkRRect::kComplex_Type: { |
- /** |
- * The x and y radii of each arc are stored in separate vectors, |
- * in the following order: |
- * |
- * __x1 _ _ _ x3__ |
- * y1 | | y2 |
- * |
- * | | |
- * |
- * y3 |__ _ _ _ __| y4 |
- * x2 x4 |
- * |
- */ |
- float twoOverW = 2 / rrect.width(); |
- float twoOverH = 2 / rrect.height(); |
- const SkVector& radiiTL = rrect.radii(SkRRect::kUpperLeft_Corner); |
- const SkVector& radiiTR = rrect.radii(SkRRect::kUpperRight_Corner); |
- const SkVector& radiiBR = rrect.radii(SkRRect::kLowerRight_Corner); |
- const SkVector& radiiBL = rrect.radii(SkRRect::kLowerLeft_Corner); |
- this->appendParamsTexel(radiiTL.x() * twoOverW, radiiBL.x() * twoOverW, |
- radiiTR.x() * twoOverW, radiiBR.x() * twoOverW); |
- this->appendParamsTexel(radiiTL.y() * twoOverH, radiiTR.y() * twoOverH, |
- radiiBL.y() * twoOverH, radiiBR.y() * twoOverH); |
- return; |
- } |
- default: return; |
- } |
-} |
- |
-void InstancedRendering::Batch::appendParamsTexel(const SkScalar* vals, int count) { |
- SkASSERT(!fIsTracked); |
- SkASSERT(count <= 4 && count >= 0); |
- const float* valsAsFloats = vals; // Ensure SkScalar == float. |
- memcpy(&fParams.push_back(), valsAsFloats, count * sizeof(float)); |
- fInfo.fHasParams = true; |
-} |
- |
-void InstancedRendering::Batch::appendParamsTexel(SkScalar x, SkScalar y, SkScalar z, SkScalar w) { |
- SkASSERT(!fIsTracked); |
- ParamsTexel& texel = fParams.push_back(); |
- texel.fX = SkScalarToFloat(x); |
- texel.fY = SkScalarToFloat(y); |
- texel.fZ = SkScalarToFloat(z); |
- texel.fW = SkScalarToFloat(w); |
- fInfo.fHasParams = true; |
-} |
- |
-void InstancedRendering::Batch::appendParamsTexel(SkScalar x, SkScalar y, SkScalar z) { |
- SkASSERT(!fIsTracked); |
- ParamsTexel& texel = fParams.push_back(); |
- texel.fX = SkScalarToFloat(x); |
- texel.fY = SkScalarToFloat(y); |
- texel.fZ = SkScalarToFloat(z); |
- fInfo.fHasParams = true; |
-} |
- |
-void InstancedRendering::Batch::initBatchTracker(const GrXPOverridesForBatch& overrides) { |
- Draw& draw = this->getSingleDraw(); // This will assert if we have > 1 command. |
- SkASSERT(draw.fGeometry.isEmpty()); |
- SkASSERT(SkIsPow2(fInfo.fShapeTypes)); |
- SkASSERT(!fIsTracked); |
- |
- if (kRect_ShapeFlag == fInfo.fShapeTypes) { |
- draw.fGeometry = InstanceProcessor::GetIndexRangeForRect(fInfo.fAntialiasMode); |
- } else if (kOval_ShapeFlag == fInfo.fShapeTypes) { |
- draw.fGeometry = InstanceProcessor::GetIndexRangeForOval(fInfo.fAntialiasMode, fBounds); |
- } else { |
- draw.fGeometry = InstanceProcessor::GetIndexRangeForRRect(fInfo.fAntialiasMode); |
- } |
- |
- if (!fParams.empty()) { |
- SkASSERT(fInstancedRendering->fParams.count() < (int)kParamsIdx_InfoMask); // TODO: cleaner. |
- this->getSingleInstance().fInfo |= fInstancedRendering->fParams.count(); |
- fInstancedRendering->fParams.push_back_n(fParams.count(), fParams.begin()); |
- } |
- |
- GrColor overrideColor; |
- if (overrides.getOverrideColorIfSet(&overrideColor)) { |
- SkASSERT(State::kRecordingDraws == fInstancedRendering->fState); |
- this->getSingleInstance().fColor = overrideColor; |
- } |
- fInfo.fUsesLocalCoords = overrides.readsLocalCoords(); |
- fInfo.fCannotTweakAlphaForCoverage = !overrides.canTweakAlphaForCoverage(); |
- |
- fInstancedRendering->fTrackedBatches.addToTail(this); |
- fIsTracked = true; |
-} |
- |
-bool InstancedRendering::Batch::onCombineIfPossible(GrBatch* other, const GrCaps& caps) { |
- Batch* that = static_cast<Batch*>(other); |
- SkASSERT(fInstancedRendering == that->fInstancedRendering); |
- SkASSERT(fTailDraw); |
- SkASSERT(that->fTailDraw); |
- |
- if (!fInfo.canJoin(that->fInfo) || |
- !GrPipeline::CanCombine(*this->pipeline(), this->bounds(), |
- *that->pipeline(), that->bounds(), caps)) { |
- return false; |
- } |
- |
- fBounds.join(that->fBounds); |
- fInfo.join(that->fInfo); |
- |
- // Adopt the other batch's draws. |
- fNumDraws += that->fNumDraws; |
- fNumChangesInGeometry += that->fNumChangesInGeometry; |
- if (fTailDraw->fGeometry != that->fHeadDraw->fGeometry) { |
- ++fNumChangesInGeometry; |
- } |
- fTailDraw->fNext = that->fHeadDraw; |
- fTailDraw = that->fTailDraw; |
- |
- that->fHeadDraw = that->fTailDraw = nullptr; |
- |
- return true; |
-} |
- |
-void InstancedRendering::Batch::computePipelineOptimizations(GrInitInvariantOutput* color, |
- GrInitInvariantOutput* coverage, |
- GrBatchToXPOverrides* overrides) const { |
- // We need to be careful about fInfo here and consider how it might change as batches combine. |
- // e.g. We can't make an assumption based on fInfo.isSimpleRects() because the batch might |
- // later combine with a non-rect. |
- color->setUnknownFourComponents(); |
- if (fInfo.fAntialiasMode >= AntialiasMode::kMSAA) { |
- coverage->setKnownSingleComponent(255); |
- } else if (AntialiasMode::kNone == fInfo.fAntialiasMode && !fInfo.fCannotDiscard) { |
- coverage->setKnownSingleComponent(255); |
- } else { |
- coverage->setUnknownSingleComponent(); |
- } |
-} |
- |
-void InstancedRendering::beginFlush(GrResourceProvider* rp) { |
- SkASSERT(State::kRecordingDraws == fState); |
- fState = State::kFlushing; |
- |
- if (fTrackedBatches.isEmpty()) { |
- return; |
- } |
- |
- if (!fVertexBuffer) { |
- fVertexBuffer.reset(InstanceProcessor::FindOrCreateVertexBuffer(fGpu)); |
- if (!fVertexBuffer) { |
- return; |
- } |
- } |
- |
- if (!fIndexBuffer) { |
- fIndexBuffer.reset(InstanceProcessor::FindOrCreateIndex8Buffer(fGpu)); |
- if (!fIndexBuffer) { |
- return; |
- } |
- } |
- |
- if (!fParams.empty()) { |
- fParamsBuffer.reset(rp->createBuffer(fParams.count() * sizeof(ParamsTexel), |
- kTexel_GrBufferType, kDynamic_GrAccessPattern, |
- GrResourceProvider::kNoPendingIO_Flag, |
- fParams.begin())); |
- if (!fParamsBuffer) { |
- return; |
- } |
- } |
- |
- this->onBeginFlush(rp); |
-} |
- |
-void InstancedRendering::Batch::onDraw(GrBatchFlushState* state) { |
- SkASSERT(State::kFlushing == fInstancedRendering->fState); |
- SkASSERT(state->gpu() == fInstancedRendering->gpu()); |
- |
- state->gpu()->handleDirtyContext(); |
- if (GrXferBarrierType barrierType = this->pipeline()->xferBarrierType(*state->gpu()->caps())) { |
- state->gpu()->xferBarrier(this->pipeline()->getRenderTarget(), barrierType); |
- } |
- |
- InstanceProcessor instProc(fInfo, fInstancedRendering->fParamsBuffer); |
- fInstancedRendering->onDraw(*this->pipeline(), instProc, this); |
-} |
- |
-void InstancedRendering::endFlush() { |
- // The caller is expected to delete all tracked batches (i.e. batches whose initBatchTracker |
- // method has been called) before ending the flush. |
- SkASSERT(fTrackedBatches.isEmpty()); |
- fParams.reset(); |
- fParamsBuffer.reset(); |
- this->onEndFlush(); |
- fState = State::kRecordingDraws; |
- // Hold on to the shape coords and index buffers. |
-} |
- |
-void InstancedRendering::resetGpuResources(ResetType resetType) { |
- fVertexBuffer.reset(); |
- fIndexBuffer.reset(); |
- fParamsBuffer.reset(); |
- this->onResetGpuResources(resetType); |
-} |
- |
-} |