Always call endFlush on opLists that might survive a flush

We were missing a few that got unreffed due to failed proxy
instantiation.

Bug: skia:7655
Bug: skia:7111
Change-Id: I95847a16890f2993a1433d4d9fdaa8a4a6c2f0b6
Reviewed-on: https://skia-review.googlesource.com/122121
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2018-04-18 13:24:25 -06:00 committed by Skia Commit-Bot
parent 15a64e71f6
commit 91ab155884
6 changed files with 48 additions and 10 deletions

View File

@ -52,7 +52,7 @@ struct GrMockOptions {
bool fTexturable = false;
};
// GPU options.
// GrCaps options.
bool fInstanceAttribSupport = false;
uint32_t fMapBufferFlags = 0;
int fMaxTextureSize = 2048;
@ -60,7 +60,7 @@ struct GrMockOptions {
int fMaxVertexAttributes = 16;
ConfigOptions fConfigOptions[kGrPixelConfigCnt];
// Shader options.
// GrShaderCaps options.
bool fGeometryShaderSupport = false;
bool fTexelBufferSupport = false;
bool fIntegerSupport = false;
@ -68,6 +68,9 @@ struct GrMockOptions {
int fMaxVertexSamplers = 0;
int fMaxFragmentSamplers = 8;
bool fShaderDerivativeSupport = true;
// GrMockGpu options.
bool fFailTextureAllocations = false;
};
#endif

View File

@ -226,6 +226,14 @@ GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*,
}
}
#ifdef SK_DEBUG
for (const auto& opList : fOpLists) {
// If there are any remaining opLists at this point, make sure they will not survive the
// flush. Otherwise we need to call endFlush() on them.
// http://skbug.com/7111
SkASSERT(!opList || opList->unique());
}
#endif
fOpLists.reset();
GrSemaphoresSubmitted result = gpu->finishFlush(numSemaphores, backendSemaphores);
@ -246,6 +254,13 @@ GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*,
return result;
}
static void end_oplist_flush_if_not_unique(const sk_sp<GrOpList>& opList) {
if (!opList->unique()) {
// TODO: Eventually this should be guaranteed unique: http://skbug.com/7111
opList->endFlush();
}
}
bool GrDrawingManager::executeOpLists(int startIndex, int stopIndex, GrOpFlushState* flushState) {
SkASSERT(startIndex <= stopIndex && stopIndex <= fOpLists.count());
@ -260,12 +275,14 @@ bool GrDrawingManager::executeOpLists(int startIndex, int stopIndex, GrOpFlushSt
if (resourceProvider->explicitlyAllocateGPUResources()) {
if (!fOpLists[i]->isInstantiated()) {
// If the backing surface wasn't allocated drop the draw of the entire opList.
end_oplist_flush_if_not_unique(fOpLists[i]); // http://skbug.com/7111
fOpLists[i] = nullptr;
continue;
}
} else {
if (!fOpLists[i]->instantiate(resourceProvider)) {
SkDebugf("OpList failed to instantiate.\n");
end_oplist_flush_if_not_unique(fOpLists[i]); // http://skbug.com/7111
fOpLists[i] = nullptr;
continue;
}
@ -313,11 +330,7 @@ bool GrDrawingManager::executeOpLists(int startIndex, int stopIndex, GrOpFlushSt
if (!fOpLists[i]) {
continue;
}
if (!fOpLists[i]->unique()) {
// TODO: Eventually this should be guaranteed unique.
// https://bugs.chromium.org/p/skia/issues/detail?id=7111
fOpLists[i]->endFlush();
}
end_oplist_flush_if_not_unique(fOpLists[i]); // http://skbug.com/7111
fOpLists[i] = nullptr;
}

View File

@ -205,8 +205,14 @@ private:
struct RTPendingPaths {
~RTPendingPaths() {
// Ensure all DrawPathsOps in this opList have been deleted.
SkASSERT(fDrawOps.isEmpty());
// Ensure there are no surviving DrawPathsOps with a dangling pointer into this class.
if (!fDrawOps.isEmpty()) {
SK_ABORT("CCPR DrawPathsOp(s) not deleted during flush");
}
// Clip lazy proxies also reference this class from their callbacks, but those callbacks
// are only invoked at flush time while we are still alive. (Unlike DrawPathsOps, that
// unregister themselves upon destruction.) So it shouldn't matter if any clip proxies
// are still around.
}
SkTInternalLList<DrawPathsOp> fDrawOps;

View File

@ -69,12 +69,17 @@ void GrMockGpu::submitCommandBuffer(const GrMockGpuRTCommandBuffer* cmdBuffer) {
GrMockGpu::GrMockGpu(GrContext* context, const GrMockOptions& options,
const GrContextOptions& contextOptions)
: INHERITED(context) {
: INHERITED(context)
, fMockOptions(options) {
fCaps.reset(new GrMockCaps(contextOptions, options));
}
sk_sp<GrTexture> GrMockGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
const GrMipLevel texels[], int mipLevelCount) {
if (fMockOptions.fFailTextureAllocations) {
return nullptr;
}
GrMipMapsStatus mipMapsStatus = mipLevelCount > 1 ? GrMipMapsStatus::kValid
: GrMipMapsStatus::kNotAllocated;
GrMockTextureInfo texInfo;

View File

@ -126,6 +126,8 @@ private:
void testingOnly_flushGpuAndSync() override {}
#endif
const GrMockOptions fMockOptions;
static int NextInternalTextureID();
static int NextExternalTextureID();
static int NextInternalRenderTargetID();

View File

@ -126,6 +126,7 @@ public:
mockOptions.fGeometryShaderSupport = true;
mockOptions.fIntegerSupport = true;
mockOptions.fFlatInterpolationSupport = true;
this->customizeMockOptions(&mockOptions);
GrContextOptions ctxOptions;
ctxOptions.fAllowPathMaskCaching = false;
@ -154,6 +155,7 @@ public:
virtual ~CCPRTest() {}
protected:
virtual void customizeMockOptions(GrMockOptions*) {}
virtual void onRun(skiatest::Reporter* reporter, CCPRPathDrawer& ccpr) = 0;
sk_sp<GrContext> fMockContext;
@ -192,6 +194,13 @@ class GrCCPRTest_cleanup : public CCPRTest {
};
DEF_CCPR_TEST(GrCCPRTest_cleanup)
class GrCCPRTest_cleanupWithTexAllocFail : public GrCCPRTest_cleanup {
void customizeMockOptions(GrMockOptions* options) override {
options->fFailTextureAllocations = true;
}
};
DEF_CCPR_TEST(GrCCPRTest_cleanupWithTexAllocFail)
class GrCCPRTest_unregisterCulledOps : public CCPRTest {
void onRun(skiatest::Reporter* reporter, CCPRPathDrawer& ccpr) override {
REPORTER_ASSERT(reporter, SkPathPriv::TestingOnly_unique(fPath));