Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Unified Diff: src/gpu/gl/GrGLNameAllocator.cpp

Issue 1150243003: Simplify path allocation, clean up resources correctly (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/gl/GrGLNameAllocator.h ('k') | src/gpu/gl/GrGLPathRendering.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/gl/GrGLNameAllocator.cpp
diff --git a/src/gpu/gl/GrGLNameAllocator.cpp b/src/gpu/gl/GrGLNameAllocator.cpp
deleted file mode 100644
index 03123a6d86ea7e87e1afe345039412b79c1ff84b..0000000000000000000000000000000000000000
--- a/src/gpu/gl/GrGLNameAllocator.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrGLNameAllocator.h"
-
-/**
- * This is the abstract base class for a nonempty AVL tree that tracks allocated
- * names within the half-open range [fFirst, fEnd). The inner nodes can be
- * sparse (meaning not every name within the range is necessarily allocated),
- * but the bounds are tight, so fFirst *is* guaranteed to be allocated, and so
- * is fEnd - 1.
- */
-class GrGLNameAllocator::SparseNameRange : public SkRefCnt {
-public:
- virtual ~SparseNameRange() {}
-
- /**
- * Return the beginning of the range. first() is guaranteed to be allocated.
- *
- * @return The first name in the range.
- */
- GrGLuint first() const { return fFirst; }
-
- /**
- * Return the end of the range. end() - 1 is guaranteed to be allocated.
- *
- * @return One plus the final name in the range.
- */
- GrGLuint end() const { return fEnd; }
-
- /**
- * Return the height of the tree. This can only be nonzero at an inner node.
- *
- * @return 0 if the implementation is a leaf node,
- * The nonzero height of the tree otherwise.
- */
- GrGLuint height() const { return fHeight; }
-
- /**
- * Allocate a name from strictly inside this range. The call will fail if
- * there is not a free name within.
- *
- * @param outName A pointer that receives the allocated name. outName will
- * be set to zero if there were no free names within the
- * range [fFirst, fEnd).
- * @return The resulting SparseNameRange after the allocation. Note that
- * this call is destructive, so the original SparseNameRange will no
- * longer be valid afterward. The caller must always update its
- * pointer with the new SparseNameRange.
- */
- virtual SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* outName) = 0;
-
- /**
- * Remove the leftmost leaf node from this range (or the entire thing if it
- * *is* a leaf node). This is an internal helper method that is used after
- * an allocation if one contiguous range became adjacent to another. (The
- * range gets removed so the one immediately before can be extended,
- * collapsing the two into one.)
- *
- * @param removedCount A pointer that receives the size of the contiguous
- range that was removed.
- * @return The resulting SparseNameRange after the removal (or nullptr if it
- * became empty). Note that this call is destructive, so the
- * original SparseNameRange will no longer be valid afterward. The
- * caller must always update its pointer with the new
- * SparseNameRange.
- */
- virtual SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange(GrGLuint* removedCount) = 0;
-
- /**
- * Append adjacent allocated names to the end of this range. This operation
- * does not affect the structure of the tree. The caller is responsible for
- * ensuring the new names won't overlap sibling ranges, if any.
- *
- * @param count The number of adjacent names to append.
- * @return The first name appended.
- */
- virtual GrGLuint appendNames(GrGLuint count) = 0;
-
- /**
- * Prepend adjacent allocated names behind the beginning of this range. This
- * operation does not affect the structure of the tree. The caller is
- * responsible for ensuring the new names won't overlap sibling ranges, if
- * any.
- *
- * @param count The number of adjacent names to prepend.
- * @return The final name prepended (the one with the lowest value).
- */
- virtual GrGLuint prependNames(GrGLuint count) = 0;
-
- /**
- * Free a name so it is no longer tracked as allocated. If the name is at
- * the very beginning or very end of the range, the boundaries [fFirst, fEnd)
- * will be tightened.
- *
- * @param name The name to free. Not-allocated names are silently ignored
- * the same way they are in the OpenGL spec.
- * @return The resulting SparseNameRange after the free (or nullptr if it
- * became empty). Note that this call is destructive, so the
- * original SparseNameRange will no longer be valid afterward. The
- * caller must always update its pointer with the new
- * SparseNameRange.
- */
- virtual SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) = 0;
-
-protected:
- SparseNameRange* takeRef() {
- this->ref();
- return this;
- }
-
- GrGLuint fFirst;
- GrGLuint fEnd;
- GrGLuint fHeight;
-};
-
-/**
- * This class is the SparseNameRange implementation for an inner node. It is an
- * AVL tree with non-null, non-adjacent left and right children.
- */
-class GrGLNameAllocator::SparseNameTree : public SparseNameRange {
-public:
- SparseNameTree(SparseNameRange* left, SparseNameRange* right)
- : fLeft(left),
- fRight(right) {
- SkASSERT(fLeft.get());
- SkASSERT(fRight.get());
- this->updateStats();
- }
-
- SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* outName) override {
- // Try allocating the range inside fLeft's internal gaps.
- fLeft.reset(fLeft->internalAllocate(outName));
- if (0 != *outName) {
- this->updateStats();
- return this->rebalance();
- }
-
- if (fLeft->end() + 1 == fRight->first()) {
- // It closed the gap between fLeft and fRight; merge.
- GrGLuint removedCount;
- fRight.reset(fRight->removeLeftmostContiguousRange(&removedCount));
- *outName = fLeft->appendNames(1 + removedCount);
- if (nullptr == fRight.get()) {
- return fLeft.detach();
- }
- this->updateStats();
- return this->rebalance();
- }
-
- // There is guaranteed to be a gap between fLeft and fRight, and the
- // "size 1" case has already been covered.
- SkASSERT(fLeft->end() + 1 < fRight->first());
- *outName = fLeft->appendNames(1);
- return this->takeRef();
- }
-
- SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange(GrGLuint* removedCount) override {
- fLeft.reset(fLeft->removeLeftmostContiguousRange(removedCount));
- if (nullptr == fLeft) {
- return fRight.detach();
- }
- this->updateStats();
- return this->rebalance();
- }
-
- GrGLuint appendNames(GrGLuint count) override {
- SkASSERT(fEnd + count > fEnd); // Check for integer wrap.
- GrGLuint name = fRight->appendNames(count);
- SkASSERT(fRight->end() == fEnd + count);
- this->updateStats();
- return name;
- }
-
- GrGLuint prependNames(GrGLuint count) override {
- SkASSERT(fFirst > count); // We can't allocate at or below 0.
- GrGLuint name = fLeft->prependNames(count);
- SkASSERT(fLeft->first() == fFirst - count);
- this->updateStats();
- return name;
- }
-
- SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) override {
- if (name < fLeft->end()) {
- fLeft.reset(fLeft->free(name));
- if (nullptr == fLeft) {
- // fLeft became empty after the free.
- return fRight.detach();
- }
- this->updateStats();
- return this->rebalance();
- } else {
- fRight.reset(fRight->free(name));
- if (nullptr == fRight) {
- // fRight became empty after the free.
- return fLeft.detach();
- }
- this->updateStats();
- return this->rebalance();
- }
- }
-
-private:
- typedef SkAutoTUnref<SparseNameRange> SparseNameTree::* ChildRange;
-
- SparseNameRange* SK_WARN_UNUSED_RESULT rebalance() {
- if (fLeft->height() > fRight->height() + 1) {
- return this->rebalanceImpl<&SparseNameTree::fLeft, &SparseNameTree::fRight>();
- }
- if (fRight->height() > fLeft->height() + 1) {
- return this->rebalanceImpl<&SparseNameTree::fRight, &SparseNameTree::fLeft>();
- }
- return this->takeRef();
- }
-
- /**
- * Rebalance the tree using rotations, as described in the AVL algorithm:
- * http://en.wikipedia.org/wiki/AVL_tree#Insertion
- */
- template<ChildRange Tall, ChildRange Short>
- SparseNameRange* SK_WARN_UNUSED_RESULT rebalanceImpl() {
- // We should be calling rebalance() enough that the tree never gets more
- // than one rotation off balance.
- SkASSERT(2 == (this->*Tall)->height() - (this->*Short)->height());
-
- // Ensure we are in the 'Left Left' or 'Right Right' case:
- // http://en.wikipedia.org/wiki/AVL_tree#Insertion
- SparseNameTree* tallChild = static_cast<SparseNameTree*>((this->*Tall).get());
- if ((tallChild->*Tall)->height() < (tallChild->*Short)->height()) {
- (this->*Tall).reset(tallChild->rotate<Short, Tall>());
- }
-
- // Perform a rotation to balance the tree.
- return this->rotate<Tall, Short>();
- }
-
- /**
- * Perform a node rotation, as described in the AVL algorithm:
- * http://en.wikipedia.org/wiki/AVL_tree#Insertion
- */
- template<ChildRange Tall, ChildRange Short>
- SparseNameRange* SK_WARN_UNUSED_RESULT rotate() {
- SparseNameTree* newRoot = static_cast<SparseNameTree*>((this->*Tall).detach());
-
- (this->*Tall).reset((newRoot->*Short).detach());
- this->updateStats();
-
- (newRoot->*Short).reset(this->takeRef());
- newRoot->updateStats();
-
- return newRoot;
- }
-
- void updateStats() {
- SkASSERT(fLeft->end() < fRight->first()); // There must be a gap between left and right.
- fFirst = fLeft->first();
- fEnd = fRight->end();
- fHeight = 1 + SkMax32(fLeft->height(), fRight->height());
- }
-
- SkAutoTUnref<SparseNameRange> fLeft;
- SkAutoTUnref<SparseNameRange> fRight;
-};
-
-/**
- * This class is the SparseNameRange implementation for a leaf node. It just a
- * contiguous range of allocated names.
- */
-class GrGLNameAllocator::ContiguousNameRange : public SparseNameRange {
-public:
- ContiguousNameRange(GrGLuint first, GrGLuint end) {
- SkASSERT(first < end);
- fFirst = first;
- fEnd = end;
- fHeight = 0;
- }
-
- SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* outName) override {
- *outName = 0; // No internal gaps, we are contiguous.
- return this->takeRef();
- }
-
- SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange(GrGLuint* removedCount) override {
- *removedCount = fEnd - fFirst;
- return nullptr;
- }
-
- GrGLuint appendNames(GrGLuint count) override {
- SkASSERT(fEnd + count > fEnd); // Check for integer wrap.
- GrGLuint name = fEnd;
- fEnd += count;
- return name;
- }
-
- GrGLuint prependNames(GrGLuint count) override {
- SkASSERT(fFirst > count); // We can't allocate at or below 0.
- fFirst -= count;
- return fFirst;
- }
-
- SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) override {
- if (name < fFirst || name >= fEnd) {
- // Not-allocated names are silently ignored.
- return this->takeRef();
- }
-
- if (fFirst == name) {
- ++fFirst;
- return (fEnd == fFirst) ? nullptr : this->takeRef();
- }
-
- if (fEnd == name + 1) {
- --fEnd;
- return this->takeRef();
- }
-
- SparseNameRange* left = new ContiguousNameRange(fFirst, name);
- SparseNameRange* right = this->takeRef();
- fFirst = name + 1;
- return new SparseNameTree(left, right);
- }
-};
-
-GrGLNameAllocator::GrGLNameAllocator(GrGLuint firstName, GrGLuint endName)
- : fFirstName(firstName),
- fEndName(endName) {
- SkASSERT(firstName > 0);
- SkASSERT(endName > firstName);
-}
-
-GrGLNameAllocator::~GrGLNameAllocator() {
-}
-
-GrGLuint GrGLNameAllocator::allocateName() {
- if (nullptr == fAllocatedNames.get()) {
- fAllocatedNames.reset(new ContiguousNameRange(fFirstName, fFirstName + 1));
- return fFirstName;
- }
-
- if (fAllocatedNames->first() > fFirstName) {
- return fAllocatedNames->prependNames(1);
- }
-
- GrGLuint name;
- fAllocatedNames.reset(fAllocatedNames->internalAllocate(&name));
- if (0 != name) {
- return name;
- }
-
- if (fAllocatedNames->end() < fEndName) {
- return fAllocatedNames->appendNames(1);
- }
-
- // Out of names.
- return 0;
-}
-
-void GrGLNameAllocator::free(GrGLuint name) {
- if (!fAllocatedNames.get()) {
- // Not-allocated names are silently ignored.
- return;
- }
-
- fAllocatedNames.reset(fAllocatedNames->free(name));
-}
« no previous file with comments | « src/gpu/gl/GrGLNameAllocator.h ('k') | src/gpu/gl/GrGLPathRendering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698