Don't flush on read/write pixels unless necessary

BUG=skia:2889

Committed: https://skia.googlesource.com/skia/+/150723b9298772a5096bec7acd2999c5c9d66239

R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/586073002
This commit is contained in:
bsalomon 2014-09-22 12:21:08 -07:00 committed by Commit bot
parent ee902cd4f4
commit 8d034a154f
5 changed files with 59 additions and 9 deletions

View File

@ -80,9 +80,14 @@ public:
#endif #endif
} }
protected: protected:
GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) {} GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) {}
bool internalHasPendingRead() const { return SkToBool(fPendingReads); }
bool internalHasPendingWrite() const { return SkToBool(fPendingWrites); }
bool internalHasPendingIO() const { return SkToBool(fPendingWrites | fPendingReads); }
private: private:
void addPendingRead() const { void addPendingRead() const {
this->validate(); this->validate();

View File

@ -135,6 +135,10 @@ public:
*/ */
bool savePixels(const char* filename); bool savePixels(const char* filename);
bool hasPendingRead() const;
bool hasPendingWrite() const;
bool hasPendingIO() const;
protected: protected:
GrSurface(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc) GrSurface(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
: INHERITED(gpu, isWrapped) : INHERITED(gpu, isWrapped)

View File

@ -1347,7 +1347,7 @@ bool GrContext::writeTexturePixels(GrTexture* texture,
} }
} }
if (!(kDontFlush_PixelOpsFlag & flags)) { if (!(kDontFlush_PixelOpsFlag & flags) && texture->hasPendingIO()) {
this->flush(); this->flush();
} }
@ -1418,7 +1418,7 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
} }
} }
if (!(kDontFlush_PixelOpsFlag & flags)) { if (!(kDontFlush_PixelOpsFlag & flags) && target->hasPendingWrite()) {
this->flush(); this->flush();
} }
@ -1578,11 +1578,10 @@ void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint*
} }
ASSERT_OWNED_RESOURCE(src); ASSERT_OWNED_RESOURCE(src);
// Writes pending to the source texture are not tracked, so a flush
// is required to ensure that the copy captures the most recent contents if (src->hasPendingWrite() || dst->hasPendingIO()) {
// of the source texture. See similar behavior in this->flush();
// GrContext::resolveRenderTarget. }
this->flush();
GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit); GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
GrDrawState* drawState = fGpu->drawState(); GrDrawState* drawState = fGpu->drawState();
@ -1715,9 +1714,15 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* target,
return false; return false;
} }
// TODO: Usually this could go to fDrawBuffer but currently
// writeRenderTargetPixels can be called in the midst of drawing another // writeRenderTargetPixels can be called in the midst of drawing another
// object (e.g., when uploading a SW path rendering to the gpu while // object (e.g., when uploading a SW path rendering to the gpu while
// drawing a rect) so preserve the current geometry. // drawing a rect). So we always draw directly to GrGpu and preserve the current geometry.
// But that means we also have to flush the draw buffer if there is a pending IO operation to
// the render target.
if (!(kDontFlush_PixelOpsFlag & flags) && target->hasPendingIO()) {
this->flush();
}
SkMatrix matrix; SkMatrix matrix;
matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix); GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix);

View File

@ -833,7 +833,7 @@ void GrInOrderDrawBuffer::geometrySourceWillPop(const GeometrySrcState& restored
void GrInOrderDrawBuffer::recordStateIfNecessary() { void GrInOrderDrawBuffer::recordStateIfNecessary() {
if (fStates.empty()) { if (fStates.empty()) {
fStates.push_back() = this->getDrawState(); this->convertDrawStateToPendingExec(&fStates.push_back(this->getDrawState()));
this->addToCmdBuffer(kSetState_Cmd); this->addToCmdBuffer(kSetState_Cmd);
return; return;
} }

View File

@ -44,3 +44,39 @@ bool GrSurface::savePixels(const char* filename) {
return true; return true;
} }
bool GrSurface::hasPendingRead() const {
const GrTexture* thisTex = this->asTexture();
if (thisTex && thisTex->internalHasPendingRead()) {
return true;
}
const GrRenderTarget* thisRT = this->asRenderTarget();
if (thisRT && thisRT->internalHasPendingRead()) {
return true;
}
return false;
}
bool GrSurface::hasPendingWrite() const {
const GrTexture* thisTex = this->asTexture();
if (thisTex && thisTex->internalHasPendingWrite()) {
return true;
}
const GrRenderTarget* thisRT = this->asRenderTarget();
if (thisRT && thisRT->internalHasPendingWrite()) {
return true;
}
return false;
}
bool GrSurface::hasPendingIO() const {
const GrTexture* thisTex = this->asTexture();
if (thisTex && thisTex->internalHasPendingIO()) {
return true;
}
const GrRenderTarget* thisRT = this->asRenderTarget();
if (thisRT && thisRT->internalHasPendingIO()) {
return true;
}
return false;
}