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

Unified Diff: gpu/command_buffer/service/path_manager.cc

Issue 169403005: command_buffer: Implement path rendering functions for CHROMIUM_path_rendering (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@nv-pr-02-texgen
Patch Set: fix windows build Created 5 years, 5 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 | « gpu/command_buffer/service/path_manager.h ('k') | gpu/command_buffer/service/path_manager_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/command_buffer/service/path_manager.cc
diff --git a/gpu/command_buffer/service/path_manager.cc b/gpu/command_buffer/service/path_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3e0d257e1a04724cc5bbbb901665f1be2148a1ae
--- /dev/null
+++ b/gpu/command_buffer/service/path_manager.cc
@@ -0,0 +1,252 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/path_manager.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace gpu {
+namespace gles2 {
+
+namespace {
+void CallDeletePaths(GLuint first_id, GLuint range) {
+ while (range > 0) {
+ GLsizei irange;
+ if (range > static_cast<GLuint>(std::numeric_limits<GLsizei>::max()))
+ irange = std::numeric_limits<GLsizei>::max();
+ else
+ irange = static_cast<GLsizei>(range);
+
+ glDeletePathsNV(first_id, irange);
+ range -= irange;
+ first_id += irange;
+ }
+}
+
+template <typename RangeIterator>
+static GLuint RangeSize(const RangeIterator& it) {
+ return it->second.last_client_id - it->first + 1;
+}
+template <typename RangeIterator>
+static GLuint FirstClientId(const RangeIterator& it) {
+ return it->first;
+}
+template <typename RangeIterator>
+static GLuint FirstServiceId(const RangeIterator& it) {
+ return it->second.first_service_id;
+}
+template <typename RangeIterator>
+static GLuint LastServiceId(const RangeIterator& it) {
+ return FirstServiceId(it) + RangeSize(it) - 1;
+}
+static GLuint LastClientId(PathManager::PathRangeMap::const_iterator& it) {
+ return it->second.last_client_id;
+}
+// Note: this one can be assigned to.
+static GLuint& LastClientId(PathManager::PathRangeMap::iterator& it) {
+ return it->second.last_client_id;
+}
+
+template <typename T>
+struct IteratorSelector {
+ typedef typename T::iterator iterator;
+};
+template <typename T>
+struct IteratorSelector<const T> {
+ typedef typename T::const_iterator iterator;
+};
+
+// Returns the range position that contains |client_id| or
+// |PathRangeMap::iterator::end()| if |client_id| is not found.
+template <typename MapType>
+static typename IteratorSelector<MapType>::iterator GetContainingRange(
+ MapType& path_map,
+ GLuint client_id) {
+ auto it = path_map.lower_bound(client_id);
+ if (it != path_map.end() && FirstClientId(it) == client_id)
+ return it;
+ if (it != path_map.begin()) {
+ --it;
+ if (LastClientId(it) >= client_id)
+ return it;
+ }
+ return path_map.end();
+}
+
+// Returns the range position that contains |client_id|. If that is
+// not available, returns the range that has smallest
+// |first_client_id| that is bigger than |client_id|. Returns
+// |PathRangeMap::iterator::end()| if there is no such range.
+template <typename MapType>
+static typename IteratorSelector<MapType>::iterator GetContainingOrNextRange(
+ MapType& path_map,
+ GLuint client_id) {
+ auto it = path_map.lower_bound(client_id);
+ if (it != path_map.end() && FirstClientId(it) == client_id) {
+ return it;
+ }
+ if (it != path_map.begin()) {
+ --it;
+ if (LastClientId(it) >= client_id)
+ return it;
+ ++it;
+ }
+ return it;
+}
+
+} // anonymous namespace
+
+PathManager::PathManager() {
+}
+
+PathManager::~PathManager() {
+ DCHECK(path_map_.empty());
+}
+
+void PathManager::Destroy(bool have_context) {
+ if (have_context) {
+ for (PathRangeMap::const_iterator it = path_map_.begin();
+ it != path_map_.end(); ++it)
+ CallDeletePaths(FirstServiceId(it), RangeSize(it));
+ }
+ path_map_.clear();
+}
+
+void PathManager::CreatePathRange(GLuint first_client_id,
+ GLuint last_client_id,
+ GLuint first_service_id) {
+ DCHECK(first_service_id > 0u);
+ DCHECK(first_client_id > 0u);
+ DCHECK(!HasPathsInRange(first_client_id, last_client_id));
+ DCHECK(CheckConsistency());
+
+ PathRangeMap::iterator range =
+ GetContainingRange(path_map_, first_client_id - 1u);
+
+ if (range != path_map_.end() &&
+ LastServiceId(range) == first_service_id - 1u) {
+ DCHECK_EQ(LastClientId(range), first_client_id - 1u);
+ LastClientId(range) = last_client_id;
+ } else {
+ auto result = path_map_.insert(
+ std::make_pair(first_client_id,
+ PathRangeDescription(last_client_id, first_service_id)));
+ DCHECK(result.second);
+ range = result.first;
+ }
+
+ PathRangeMap::iterator next_range = range;
+ ++next_range;
+ if (next_range != path_map_.end()) {
+ if (LastClientId(range) == FirstClientId(next_range) - 1u &&
+ LastServiceId(range) == FirstServiceId(next_range) - 1u) {
+ LastClientId(range) = LastClientId(next_range);
+ path_map_.erase(next_range);
+ }
+ }
+ DCHECK(CheckConsistency());
+}
+
+bool PathManager::HasPathsInRange(GLuint first_client_id,
+ GLuint last_client_id) const {
+ PathRangeMap::const_iterator it =
+ GetContainingOrNextRange(path_map_, first_client_id);
+ if (it == path_map_.end())
+ return false;
+
+ return FirstClientId(it) <= last_client_id;
+}
+
+bool PathManager::GetPath(GLuint client_id, GLuint* service_id) const {
+ PathRangeMap::const_iterator range = GetContainingRange(path_map_, client_id);
+ if (range == path_map_.end())
+ return false;
+
+ *service_id = FirstServiceId(range) + client_id - FirstClientId(range);
+ return true;
+}
+
+void PathManager::RemovePaths(GLuint first_client_id, GLuint last_client_id) {
+ DCHECK(CheckConsistency());
+ PathRangeMap::iterator it =
+ GetContainingOrNextRange(path_map_, first_client_id);
+
+ while (it != path_map_.end() && FirstClientId(it) <= last_client_id) {
+ GLuint delete_first_client_id =
+ std::max(first_client_id, FirstClientId(it));
+ GLuint delete_last_client_id = std::min(last_client_id, LastClientId(it));
+ GLuint delete_first_service_id =
+ FirstServiceId(it) + delete_first_client_id - FirstClientId(it);
+ GLuint delete_range = delete_last_client_id - delete_first_client_id + 1u;
+
+ CallDeletePaths(delete_first_service_id, delete_range);
+
+ PathRangeMap::iterator current = it;
+ ++it;
+
+ GLuint current_last_client_id = LastClientId(current);
+
+ if (FirstClientId(current) < delete_first_client_id)
+ LastClientId(current) = delete_first_client_id - 1u;
+ else
+ path_map_.erase(current);
+
+ if (current_last_client_id > delete_last_client_id) {
+ path_map_.insert(std::make_pair(
+ delete_last_client_id + 1u,
+ PathRangeDescription(current_last_client_id,
+ delete_first_service_id + delete_range)));
+ DCHECK(delete_last_client_id == last_client_id);
+ // This is necessarily the last range to check. Return early due to
+ // consistency. Iterator increment would skip the inserted range. The
+ // algorithm would work ok, but it looks weird.
+ DCHECK(CheckConsistency());
+ return;
+ }
+ }
+ DCHECK(CheckConsistency());
+}
+
+bool PathManager::CheckConsistency() {
+ GLuint prev_first_client_id = 0u;
+ GLuint prev_last_client_id = 0u;
+ GLuint prev_first_service_id = 0u;
+ for (PathRangeMap::iterator range = path_map_.begin();
+ range != path_map_.end(); ++range) {
+ // Code relies on ranges not starting at 0. Also, the above initialization
+ // is only
+ // correct then.
+ if (FirstClientId(range) == 0u || FirstServiceId(range) == 0u)
+ return false;
+
+ // Each range is consistent.
+ if (FirstClientId(range) > LastClientId(range))
+ return false;
+
+ if (prev_first_client_id != 0u) {
+ // No overlapping ranges. (The iteration is sorted).
+ if (FirstClientId(range) <= prev_last_client_id)
+ return false;
+
+ // No mergeable ranges.
+ bool is_mergeable_client =
+ FirstClientId(range) - 1u == prev_last_client_id;
+ bool is_mergeable_service =
+ FirstServiceId(range) - 1u == prev_first_service_id;
+ if (is_mergeable_client && is_mergeable_service)
+ return false;
+ }
+ prev_first_client_id = FirstClientId(range);
+ prev_last_client_id = LastClientId(range);
+ prev_first_service_id = FirstServiceId(range);
+ }
+ return true;
+}
+
+} // namespace gles2
+} // namespace gpu
« no previous file with comments | « gpu/command_buffer/service/path_manager.h ('k') | gpu/command_buffer/service/path_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698