Index: gpu/command_buffer/service/indexed_buffer_binding_host.cc |
diff --git a/gpu/command_buffer/service/indexed_buffer_binding_host.cc b/gpu/command_buffer/service/indexed_buffer_binding_host.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e093e1dd0c3e4cde3d6bd1bcce7118cd23ac18f7 |
--- /dev/null |
+++ b/gpu/command_buffer/service/indexed_buffer_binding_host.cc |
@@ -0,0 +1,187 @@ |
+// Copyright (c) 2016 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/indexed_buffer_binding_host.h" |
+ |
+#include "gpu/command_buffer/service/buffer_manager.h" |
+ |
+namespace gpu { |
+namespace gles2 { |
+ |
+IndexedBufferBindingHost::IndexedBufferBinding::IndexedBufferBinding() |
+ : type(kBindBufferNone), |
+ offset(0), |
+ size(0), |
+ effective_full_buffer_size(0) { |
+} |
+ |
+IndexedBufferBindingHost::IndexedBufferBinding::IndexedBufferBinding( |
+ const IndexedBufferBindingHost::IndexedBufferBinding& other) |
+ : type(other.type), |
+ buffer(other.buffer.get()), |
+ offset(other.offset), |
+ size(other.size), |
+ effective_full_buffer_size(other.effective_full_buffer_size) { |
+} |
+ |
+IndexedBufferBindingHost::IndexedBufferBinding::~IndexedBufferBinding() { |
+} |
+ |
+void IndexedBufferBindingHost::IndexedBufferBinding::SetBindBufferBase( |
+ Buffer* _buffer) { |
+ if (!_buffer) { |
+ Reset(); |
+ return; |
+ } |
+ type = kBindBufferBase; |
+ buffer = _buffer; |
+ offset = 0; |
+ size = 0; |
+ effective_full_buffer_size = 0; |
+} |
+ |
+void IndexedBufferBindingHost::IndexedBufferBinding::SetBindBufferRange( |
+ Buffer* _buffer, GLintptr _offset, GLsizeiptr _size) { |
+ if (!_buffer) { |
+ Reset(); |
+ return; |
+ } |
+ type = kBindBufferRange; |
+ buffer = _buffer; |
+ offset = _offset; |
+ size = _size; |
+ effective_full_buffer_size = _buffer ? _buffer->size() : 0; |
+} |
+ |
+void IndexedBufferBindingHost::IndexedBufferBinding::Reset() { |
+ type = kBindBufferNone; |
+ buffer = nullptr; |
+ offset = 0; |
+ size = 0; |
+ effective_full_buffer_size = 0; |
+} |
+ |
+ |
+IndexedBufferBindingHost::IndexedBufferBindingHost( |
+ uint32_t max_bindings, bool needs_emulation) |
+ : needs_emulation_(needs_emulation) { |
+ buffer_bindings_.resize(max_bindings); |
+} |
+ |
+IndexedBufferBindingHost::~IndexedBufferBindingHost() { |
+} |
+ |
+void IndexedBufferBindingHost::DoBindBufferBase( |
+ GLenum target, GLuint index, Buffer* buffer) { |
+ DCHECK_LT(index, buffer_bindings_.size()); |
+ GLuint service_id = buffer ? buffer->service_id() : 0; |
+ glBindBufferBase(target, index, service_id); |
+ |
+ buffer_bindings_[index].SetBindBufferBase(buffer); |
+} |
+ |
+void IndexedBufferBindingHost::DoBindBufferRange( |
+ GLenum target, GLuint index, Buffer* buffer, GLintptr offset, |
+ GLsizeiptr size) { |
+ DCHECK_LT(index, buffer_bindings_.size()); |
+ GLuint service_id = buffer ? buffer->service_id() : 0; |
+ if (buffer && needs_emulation_) { |
+ DoAdjustedBindBufferRange( |
+ target, index, service_id, offset, size, buffer->size()); |
+ } else { |
+ glBindBufferRange(target, index, service_id, offset, size); |
+ } |
+ |
+ buffer_bindings_[index].SetBindBufferRange(buffer, offset, size); |
+} |
+ |
+// static |
+void IndexedBufferBindingHost::DoAdjustedBindBufferRange( |
+ GLenum target, GLuint index, GLuint service_id, GLintptr offset, |
+ GLsizeiptr size, GLsizeiptr full_buffer_size) { |
+ GLsizeiptr adjusted_size = size; |
+ if (offset >= full_buffer_size) { |
+ // Situation 1: We can't really call glBindBufferRange with reasonable |
+ // offset/size without triggering a GL error because size == 0 isn't |
+ // valid. |
+ // TODO(zmo): it's ambiguous in the GL 4.1 spec whether BindBufferBase |
+ // generates a GL error in such case. In reality, no error is generated on |
+ // MacOSX with AMD/4.1. |
+ glBindBufferBase(target, index, service_id); |
+ return; |
+ } else if (offset + size > full_buffer_size) { |
+ adjusted_size = full_buffer_size - offset; |
+ // size needs to be a multiple of 4. |
+ adjusted_size = adjusted_size & ~3; |
+ if (adjusted_size == 0) { |
+ // Situation 2: The original size is valid, but the adjusted size |
+ // is 0 and isn't valid. Handle it the same way as situation 1. |
+ glBindBufferBase(target, index, service_id); |
+ return; |
+ } |
+ } |
+ glBindBufferRange(target, index, service_id, offset, adjusted_size); |
+} |
+ |
+void IndexedBufferBindingHost::OnBindHost(GLenum target) { |
+ if (needs_emulation_) { |
+ // If some bound buffers change size since last time the transformfeedback |
+ // is bound, we might need to reset the ranges. |
+ for (size_t ii = 0; ii < buffer_bindings_.size(); ++ii) { |
+ Buffer* buffer = buffer_bindings_[ii].buffer.get(); |
+ if (buffer && buffer_bindings_[ii].type == kBindBufferRange && |
+ buffer_bindings_[ii].effective_full_buffer_size != buffer->size()) { |
+ DoAdjustedBindBufferRange( |
+ target, ii, buffer->service_id(), buffer_bindings_[ii].offset, |
+ buffer_bindings_[ii].size, buffer->size()); |
+ buffer_bindings_[ii].effective_full_buffer_size = buffer->size(); |
+ } |
+ } |
+ } |
+} |
+ |
+void IndexedBufferBindingHost::OnBufferData(GLenum target, Buffer* buffer) { |
+ DCHECK(buffer); |
+ if (needs_emulation_) { |
+ // If some bound buffers change size since last time the transformfeedback |
+ // is bound, we might need to reset the ranges. |
+ for (size_t ii = 0; ii < buffer_bindings_.size(); ++ii) { |
+ if (buffer_bindings_[ii].buffer.get() != buffer) |
+ continue; |
+ if (buffer_bindings_[ii].type == kBindBufferRange && |
+ buffer_bindings_[ii].effective_full_buffer_size != buffer->size()) { |
+ DoAdjustedBindBufferRange( |
+ target, ii, buffer->service_id(), buffer_bindings_[ii].offset, |
+ buffer_bindings_[ii].size, buffer->size()); |
+ buffer_bindings_[ii].effective_full_buffer_size = buffer->size(); |
+ } |
+ } |
+ } |
+} |
+ |
+void IndexedBufferBindingHost::RemoveBoundBuffer(Buffer* buffer) { |
+ for (size_t ii = 0; ii < buffer_bindings_.size(); ++ii) { |
+ if (buffer_bindings_[ii].buffer.get() == buffer) { |
+ buffer_bindings_[ii].Reset(); |
+ } |
+ } |
+} |
+ |
+Buffer* IndexedBufferBindingHost::GetBufferBinding(GLuint index) const { |
+ DCHECK_LT(index, buffer_bindings_.size()); |
+ return buffer_bindings_[index].buffer.get(); |
+} |
+ |
+GLsizeiptr IndexedBufferBindingHost::GetBufferSize(GLuint index) const { |
+ DCHECK_LT(index, buffer_bindings_.size()); |
+ return buffer_bindings_[index].size; |
+} |
+ |
+GLintptr IndexedBufferBindingHost::GetBufferStart(GLuint index) const { |
+ DCHECK_LT(index, buffer_bindings_.size()); |
+ return buffer_bindings_[index].offset; |
+} |
+ |
+} // namespace gles2 |
+} // namespace gpu |