| Index: src/gpu/GrDrawTarget.cpp
|
| diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
|
| index 0e7e6bce90225646e42e3625db8b79a32fda7b7b..7eaa8bc76219f5ecbbec22a6747da1f651c6cdf6 100644
|
| --- a/src/gpu/GrDrawTarget.cpp
|
| +++ b/src/gpu/GrDrawTarget.cpp
|
| @@ -36,7 +36,8 @@ GrDrawTarget::GrDrawTarget(GrGpu* gpu, GrResourceProvider* resourceProvider)
|
| : fGpu(SkRef(gpu))
|
| , fCaps(SkRef(gpu->caps()))
|
| , fResourceProvider(resourceProvider)
|
| - , fFlushing(false) {
|
| + , fFlushing(false)
|
| + , fLastFlushToken(0) {
|
| }
|
|
|
| GrDrawTarget::~GrDrawTarget() {
|
| @@ -119,12 +120,31 @@ void GrDrawTarget::flush() {
|
| }
|
| fFlushing = true;
|
|
|
| - this->onFlush();
|
| + GrBatchFlushState flushState(fGpu, fResourceProvider, fLastFlushToken);
|
| +
|
| + // Loop over all batches and generate geometry
|
| + for (int i = 0; i < fBatches.count(); ++i) {
|
| + fBatches[i]->prepare(&flushState);
|
| + }
|
| +
|
| + // Upload all data to the GPU
|
| + flushState.preIssueDraws();
|
| +
|
| + // Draw all the generated geometry.
|
| + for (int i = 0; i < fBatches.count(); ++i) {
|
| + fBatches[i]->draw(&flushState);
|
| + }
|
| +
|
| + fLastFlushToken = flushState.lastFlushedToken();
|
|
|
| fFlushing = false;
|
| this->reset();
|
| }
|
|
|
| +void GrDrawTarget::reset() {
|
| + fBatches.reset();
|
| +}
|
| +
|
| void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) {
|
| // Setup clip
|
| GrScissorState scissorState;
|
| @@ -148,7 +168,7 @@ void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBat
|
| if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) {
|
| return;
|
| }
|
| - this->onDrawBatch(batch);
|
| + this->recordBatch(batch);
|
| }
|
|
|
| static const GrStencilSettings& winding_path_stencil_settings() {
|
| @@ -213,7 +233,7 @@ void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
|
| stencilSettings, scissorState,
|
| pipelineBuilder.getRenderTarget(),
|
| path);
|
| - this->onDrawBatch(batch);
|
| + this->recordBatch(batch);
|
| batch->unref();
|
| }
|
|
|
| @@ -269,7 +289,7 @@ void GrDrawTarget::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
|
| return;
|
| }
|
|
|
| - this->onDrawBatch(batch);
|
| + this->recordBatch(batch);
|
| }
|
|
|
| void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
|
| @@ -344,7 +364,7 @@ void GrDrawTarget::clear(const SkIRect* rect,
|
| this->drawNonAARect(pipelineBuilder, color, SkMatrix::I(), *rect);
|
| } else {
|
| GrBatch* batch = new GrClearBatch(*rect, color, renderTarget);
|
| - this->onDrawBatch(batch);
|
| + this->recordBatch(batch);
|
| batch->unref();
|
| }
|
| }
|
| @@ -352,7 +372,7 @@ void GrDrawTarget::clear(const SkIRect* rect,
|
| void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
|
| if (this->caps()->discardRenderTargetSupport()) {
|
| GrBatch* batch = new GrDiscardBatch(renderTarget);
|
| - this->onDrawBatch(batch);
|
| + this->recordBatch(batch);
|
| batch->unref();
|
| }
|
| }
|
| @@ -365,11 +385,67 @@ void GrDrawTarget::copySurface(GrSurface* dst,
|
| const SkIPoint& dstPoint) {
|
| GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
|
| if (batch) {
|
| - this->onDrawBatch(batch);
|
| + this->recordBatch(batch);
|
| batch->unref();
|
| }
|
| }
|
|
|
| +template <class Left, class Right> static bool intersect(const Left& a, const Right& b) {
|
| + SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom &&
|
| + b.fLeft <= b.fRight && b.fTop <= b.fBottom);
|
| + return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.fTop < a.fBottom;
|
| +}
|
| +
|
| +void GrDrawTarget::recordBatch(GrBatch* batch) {
|
| + // Check if there is a Batch Draw we can batch with by linearly searching back until we either
|
| + // 1) check every draw
|
| + // 2) intersect with something
|
| + // 3) find a 'blocker'
|
| + // Experimentally we have found that most batching occurs within the first 10 comparisons.
|
| + static const int kMaxLookback = 10;
|
| +
|
| + GrBATCH_INFO("Re-Recording (%s, B%u)\n"
|
| + "\tBounds (%f, %f, %f, %f)\n",
|
| + batch->name(),
|
| + batch->uniqueID(),
|
| + batch->bounds().fLeft, batch->bounds().fRight,
|
| + batch->bounds().fTop, batch->bounds().fBottom);
|
| + GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str());
|
| + GrBATCH_INFO("\tOutcome:\n");
|
| + int maxCandidates = SkTMin(kMaxLookback, fBatches.count());
|
| + if (maxCandidates) {
|
| + int i = 0;
|
| + while (true) {
|
| + GrBatch* candidate = fBatches.fromBack(i);
|
| + // We cannot continue to search backwards if the render target changes
|
| + if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
|
| + GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
|
| + candidate->name(), candidate->uniqueID());
|
| + break;
|
| + }
|
| + if (candidate->combineIfPossible(batch, *this->caps())) {
|
| + GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
|
| + candidate->uniqueID());
|
| + return;
|
| + }
|
| + // Stop going backwards if we would cause a painter's order violation.
|
| + if (intersect(candidate->bounds(), batch->bounds())) {
|
| + GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
|
| + candidate->uniqueID());
|
| + break;
|
| + }
|
| + ++i;
|
| + if (i == maxCandidates) {
|
| + GrBATCH_INFO("\t\tReached max lookback or beginning of batch array %d\n", i);
|
| + break;
|
| + }
|
| + }
|
| + } else {
|
| + GrBATCH_INFO("\t\tFirstBatch\n");
|
| + }
|
| + fBatches.push_back().reset(SkRef(batch));
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| GrDrawTarget::PipelineInfo::PipelineInfo(const GrPipelineBuilder* pipelineBuilder,
|
| @@ -416,6 +492,6 @@ void GrClipTarget::purgeResources() {
|
|
|
| void GrClipTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
|
| GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
|
| - this->onDrawBatch(batch);
|
| + this->recordBatch(batch);
|
| batch->unref();
|
| }
|
|
|