diff options
author | 2016-01-13 23:36:45 -0800 | |
---|---|---|
committer | 2016-01-13 23:36:45 -0800 | |
commit | 702501ddca7cf9b7b941ad286a0c9aa37fda86ef (patch) | |
tree | 0f9224f82fe58a6e2a5a5a0f519173b3ae5cf0c2 /src/gpu/gl/GrGLPathRendering.cpp | |
parent | 7ddfeeddf78b78de28874432eb9a95735b56af7b (diff) |
Simplify path allocation, clean up resources correctly
Simplify path id allocation in NVPR backend. Instead of using
an AVL tree of path id ranges for the first 65535 ids, use just
a simple stategy of overallocation and "bump index".
Fixes the bug where previously overallocated ids were not deleted.
The advantage is that the implementation is simple and all allocations
go through overallocation, not just the first 65535 of the 1-range
allocations.
Removes the logic where paths were cleared with setting path data to
null instead of deleting the whole path. Now deleted paths are just
deleted normally. These operations should have equivalent performance on
command buffer. Deleting the path should enable the driver to do more
maintainance.
Removes the GLNameAllocator, as it was only used for paths. In order for
it to be used for other IDs, it probably would need to be re-written to
support cleanup and arbitrary ranges. Also, the interface would probably
need to be changed to not requiring the block to be allocated before it
could be managed by the structure.
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1150243003
Review URL: https://codereview.chromium.org/1150243003
Diffstat (limited to 'src/gpu/gl/GrGLPathRendering.cpp')
-rw-r--r-- | src/gpu/gl/GrGLPathRendering.cpp | 97 |
1 files changed, 53 insertions, 44 deletions
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp index 4c9ef86786..3cfec749ac 100644 --- a/src/gpu/gl/GrGLPathRendering.cpp +++ b/src/gpu/gl/GrGLPathRendering.cpp @@ -6,7 +6,6 @@ */ #include "gl/GrGLPathRendering.h" -#include "gl/GrGLNameAllocator.h" #include "gl/GrGLUtil.h" #include "gl/GrGLGpu.h" @@ -20,6 +19,9 @@ #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X) #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->gpu()->glInterface(), RET, X) +// Number of paths to allocate per glGenPaths call. The call can be overly slow on command buffer GL +// implementation. The call has a result value, and thus waiting for the call completion is needed. +static const GrGLsizei kPathIDPreallocationAmount = 65536; static const GrGLenum gIndexType2GLType[] = { GR_GL_UNSIGNED_BYTE, @@ -60,17 +62,21 @@ static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) { } GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu) - : GrPathRendering(gpu) { + : GrPathRendering(gpu) + , fPreallocatedPathCount(0) { const GrGLInterface* glInterface = gpu->glInterface(); fCaps.bindFragmentInputSupport = nullptr != glInterface->fFunctions.fBindFragmentInputLocation; } GrGLPathRendering::~GrGLPathRendering() { + if (fPreallocatedPathCount > 0) { + this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount); + } } void GrGLPathRendering::abandonGpuResources() { - fPathNameAllocator.reset(nullptr); + fPreallocatedPathCount = 0; } void GrGLPathRendering::resetContext() { @@ -230,54 +236,57 @@ void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix, } GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) { - if (range > 1) { - GrGLuint name; - GL_CALL_RET(name, GenPaths(range)); - return name; + SkASSERT(range > 0); + GrGLuint firstID; + if (fPreallocatedPathCount >= range) { + firstID = fFirstPreallocatedPathID; + fPreallocatedPathCount -= range; + fFirstPreallocatedPathID += range; + return firstID; } - - if (nullptr == fPathNameAllocator.get()) { - static const int range = 65536; - GrGLuint firstName; - GL_CALL_RET(firstName, GenPaths(range)); - fPathNameAllocator.reset(new GrGLNameAllocator(firstName, firstName + range)); + // Allocate range + the amount to fill up preallocation amount. If succeed, either join with + // the existing preallocation range or delete the existing and use the new (potentially partial) + // preallocation range. + GrGLsizei allocAmount = range + (kPathIDPreallocationAmount - fPreallocatedPathCount); + if (allocAmount >= range) { + GL_CALL_RET(firstID, GenPaths(allocAmount)); + + if (firstID != 0) { + if (fPreallocatedPathCount > 0 && + firstID == fFirstPreallocatedPathID + fPreallocatedPathCount) { + firstID = fFirstPreallocatedPathID; + fPreallocatedPathCount += allocAmount - range; + fFirstPreallocatedPathID += range; + return firstID; + } + + if (allocAmount > range) { + if (fPreallocatedPathCount > 0) { + this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount); + } + fFirstPreallocatedPathID = firstID + range; + fPreallocatedPathCount = allocAmount - range; + } + // Special case: if allocAmount == range, we have full preallocated range. + return firstID; + } } - - // When allocating names one at a time, pull from a client-side pool of - // available names in order to save a round trip to the GL server. - GrGLuint name = fPathNameAllocator->allocateName(); - - if (0 == name) { - // Our reserved path names are all in use. Fall back on GenPaths. - GL_CALL_RET(name, GenPaths(1)); + // Failed to allocate with preallocation. Remove existing preallocation and try to allocate just + // the range. + if (fPreallocatedPathCount > 0) { + this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount); + fPreallocatedPathCount = 0; } - return name; + GL_CALL_RET(firstID, GenPaths(range)); + if (firstID == 0) { + SkDebugf("Warning: Failed to allocate path\n"); + } + return firstID; } void GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) { - if (range > 1) { - // It is not supported to delete names in ranges that were allocated - // individually using GrGLPathNameAllocator. - SkASSERT(nullptr == fPathNameAllocator.get() || - path + range <= fPathNameAllocator->firstName() || - path >= fPathNameAllocator->endName()); - GL_CALL(DeletePaths(path, range)); - return; - } - - if (nullptr == fPathNameAllocator.get() || - path < fPathNameAllocator->firstName() || - path >= fPathNameAllocator->endName()) { - // If we aren't inside fPathNameAllocator's range then this name was - // generated by the GenPaths fallback (or else was never allocated). - GL_CALL(DeletePaths(path, 1)); - return; - } - - // Make the path empty to save memory, but don't free the name in the driver. - GL_CALL(PathCommands(path, 0, nullptr, 0, GR_GL_FLOAT, nullptr)); - fPathNameAllocator->free(path); + GL_CALL(DeletePaths(path, range)); } void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stencilSettings) { |