aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl/GrGLPathRendering.cpp
diff options
context:
space:
mode:
authorGravatar kkinnunen <kkinnunen@nvidia.com>2016-01-13 23:36:45 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-01-13 23:36:45 -0800
commit702501ddca7cf9b7b941ad286a0c9aa37fda86ef (patch)
tree0f9224f82fe58a6e2a5a5a0f519173b3ae5cf0c2 /src/gpu/gl/GrGLPathRendering.cpp
parent7ddfeeddf78b78de28874432eb9a95735b56af7b (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.cpp97
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) {