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 #include "GrOpFlushState.h" 9 10 #include "GrDrawOpAtlas.h" 11 #include "GrGpu.h" 12 #include "GrResourceProvider.h" 13 #include "GrTexture.h" 14 15 ////////////////////////////////////////////////////////////////////////////// 16 17 GrOpFlushState::GrOpFlushState(GrGpu* gpu, 18 GrResourceProvider* resourceProvider, 19 GrTokenTracker* tokenTracker) 20 : fVertexPool(gpu) 21 , fIndexPool(gpu) 22 , fGpu(gpu) 23 , fResourceProvider(resourceProvider) 24 , fTokenTracker(tokenTracker) { 25 } 26 27 const GrCaps& GrOpFlushState::caps() const { 28 return *fGpu->caps(); 29 } 30 31 GrGpuRTCommandBuffer* GrOpFlushState::rtCommandBuffer() { 32 return fCommandBuffer->asRTCommandBuffer(); 33 } 34 35 void GrOpFlushState::executeDrawsAndUploadsForMeshDrawOp(uint32_t opID, const SkRect& opBounds) { 36 SkASSERT(this->rtCommandBuffer()); 37 while (fCurrDraw != fDraws.end() && fCurrDraw->fOpID == opID) { 38 GrDeferredUploadToken drawToken = fTokenTracker->nextTokenToFlush(); 39 while (fCurrUpload != fInlineUploads.end() && 40 fCurrUpload->fUploadBeforeToken == drawToken) { 41 this->rtCommandBuffer()->inlineUpload(this, fCurrUpload->fUpload); 42 ++fCurrUpload; 43 } 44 SkASSERT(fCurrDraw->fPipeline->proxy() == this->drawOpArgs().fProxy); 45 this->rtCommandBuffer()->draw(*fCurrDraw->fPipeline, *fCurrDraw->fGeometryProcessor, 46 fMeshes.begin() + fCurrMesh, nullptr, fCurrDraw->fMeshCnt, 47 opBounds); 48 fCurrMesh += fCurrDraw->fMeshCnt; 49 fTokenTracker->flushToken(); 50 ++fCurrDraw; 51 } 52 } 53 54 void GrOpFlushState::preExecuteDraws() { 55 fVertexPool.unmap(); 56 fIndexPool.unmap(); 57 for (auto& upload : fASAPUploads) { 58 this->doUpload(upload); 59 } 60 // Setup execution iterators. 61 fCurrDraw = fDraws.begin(); 62 fCurrUpload = fInlineUploads.begin(); 63 fCurrMesh = 0; 64 } 65 66 void GrOpFlushState::reset() { 67 SkASSERT(fCurrDraw == fDraws.end()); 68 SkASSERT(fCurrUpload == fInlineUploads.end()); 69 fVertexPool.reset(); 70 fIndexPool.reset(); 71 fArena.reset(); 72 fASAPUploads.reset(); 73 fInlineUploads.reset(); 74 fDraws.reset(); 75 fMeshes.reset(); 76 fCurrMesh = 0; 77 fBaseDrawToken = GrDeferredUploadToken::AlreadyFlushedToken(); 78 } 79 80 void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload) { 81 GrDeferredTextureUploadWritePixelsFn wp = [this](GrTextureProxy* dstProxy, int left, int top, 82 int width, int height, GrPixelConfig srcConfig, 83 const void* buffer, size_t rowBytes) { 84 GrSurface* dstSurface = dstProxy->priv().peekSurface(); 85 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference; 86 GrGpu::WritePixelTempDrawInfo tempInfo; 87 if (!fGpu->getWritePixelsInfo(dstSurface, dstProxy->origin(), 88 width, height, srcConfig, 89 &drawPreference, &tempInfo)) { 90 return false; 91 } 92 if (GrGpu::kNoDraw_DrawPreference == drawPreference) { 93 return this->fGpu->writePixels(dstSurface, dstProxy->origin(), 94 left, top, width, height, 95 srcConfig, buffer, rowBytes); 96 } 97 GrSurfaceDesc desc; 98 desc.fOrigin = dstProxy->origin(); 99 desc.fWidth = width; 100 desc.fHeight = height; 101 desc.fConfig = dstProxy->config(); 102 sk_sp<GrTexture> temp(this->fResourceProvider->createApproxTexture( 103 desc, GrResourceProvider::kNoPendingIO_Flag)); 104 if (!temp) { 105 return false; 106 } 107 if (!fGpu->writePixels(temp.get(), dstProxy->origin(), 0, 0, width, height, desc.fConfig, 108 buffer, rowBytes)) { 109 return false; 110 } 111 return fGpu->copySurface(dstSurface, dstProxy->origin(), temp.get(), dstProxy->origin(), 112 SkIRect::MakeWH(width, height), {left, top}); 113 }; 114 upload(wp); 115 } 116 117 GrDeferredUploadToken GrOpFlushState::addInlineUpload(GrDeferredTextureUploadFn&& upload) { 118 return fInlineUploads.append(&fArena, std::move(upload), fTokenTracker->nextDrawToken()) 119 .fUploadBeforeToken; 120 } 121 122 GrDeferredUploadToken GrOpFlushState::addASAPUpload(GrDeferredTextureUploadFn&& upload) { 123 fASAPUploads.append(&fArena, std::move(upload)); 124 return fTokenTracker->nextTokenToFlush(); 125 } 126 127 void GrOpFlushState::draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline, 128 const GrMesh& mesh) { 129 SkASSERT(fOpArgs); 130 SkASSERT(fOpArgs->fOp); 131 fMeshes.push_back(mesh); 132 bool firstDraw = fDraws.begin() == fDraws.end(); 133 if (!firstDraw) { 134 Draw& lastDraw = *fDraws.begin(); 135 // If the last draw shares a geometry processor and pipeline and there are no intervening 136 // uploads, add this mesh to it. 137 if (lastDraw.fGeometryProcessor == gp && lastDraw.fPipeline == pipeline) { 138 if (fInlineUploads.begin() == fInlineUploads.end() || 139 fInlineUploads.tail()->fUploadBeforeToken != fTokenTracker->nextDrawToken()) { 140 ++lastDraw.fMeshCnt; 141 return; 142 } 143 } 144 } 145 auto& draw = fDraws.append(&fArena); 146 GrDeferredUploadToken token = fTokenTracker->issueDrawToken(); 147 148 draw.fGeometryProcessor.reset(gp); 149 draw.fPipeline = pipeline; 150 draw.fMeshCnt = 1; 151 draw.fOpID = fOpArgs->fOp->uniqueID(); 152 if (firstDraw) { 153 fBaseDrawToken = token; 154 } 155 } 156 157 void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer** buffer, 158 int* startVertex) { 159 return fVertexPool.makeSpace(vertexSize, vertexCount, buffer, startVertex); 160 } 161 162 uint16_t* GrOpFlushState::makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) { 163 return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex)); 164 } 165 166 void* GrOpFlushState::makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, 167 int fallbackVertexCount, const GrBuffer** buffer, 168 int* startVertex, int* actualVertexCount) { 169 return fVertexPool.makeSpaceAtLeast(vertexSize, minVertexCount, fallbackVertexCount, buffer, 170 startVertex, actualVertexCount); 171 } 172 173 uint16_t* GrOpFlushState::makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount, 174 const GrBuffer** buffer, int* startIndex, 175 int* actualIndexCount) { 176 return reinterpret_cast<uint16_t*>(fIndexPool.makeSpaceAtLeast( 177 minIndexCount, fallbackIndexCount, buffer, startIndex, actualIndexCount)); 178 } 179 180 void GrOpFlushState::putBackIndices(int indexCount) { 181 fIndexPool.putBack(indexCount * sizeof(uint16_t)); 182 } 183 184 void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) { 185 fVertexPool.putBack(vertices * vertexStride); 186 } 187 188 GrAppliedClip GrOpFlushState::detachAppliedClip() { 189 return fOpArgs->fAppliedClip ? std::move(*fOpArgs->fAppliedClip) : GrAppliedClip(); 190 } 191