summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-21 07:30:30 +0000
committerreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-21 07:30:30 +0000
commite0d6b1f946e5eba6abc2b2264d1fb64451b66b83 (patch)
treeb39a86f4a61aa95d1c119e71e110cf660bde9761 /gpu
parentf57bbc063aa387dbd7c929cacc8d55a960a28ec4 (diff)
downloadchromium_src-e0d6b1f946e5eba6abc2b2264d1fb64451b66b83.zip
chromium_src-e0d6b1f946e5eba6abc2b2264d1fb64451b66b83.tar.gz
chromium_src-e0d6b1f946e5eba6abc2b2264d1fb64451b66b83.tar.bz2
Add support for GL_CHROMIUM_pixel_transfer_buffer_object.
This adds two new types of buffer objects, GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM and GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM. The PIXEL_PACK buffer affects API calls that pack pixel data, such as glReadPixels. The PIXEL_UNPACK buffer affects API calls that unpack pixel data, such as glTexImage2D. These new buffer object are backed by shared memory, which allows clients to update them without any unnecessary copying. BUG=111096,161337 TEST=unit tests Review URL: https://chromiumcodereview.appspot.com/10440019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@168999 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py14
-rw-r--r--gpu/command_buffer/client/buffer_tracker.cc69
-rw-r--r--gpu/command_buffer/client/buffer_tracker.h103
-rw-r--r--gpu/command_buffer/client/buffer_tracker_unittest.cc74
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h10
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc188
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h19
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h4
-rw-r--r--gpu/command_buffer/client/gles2_interface_autogen.h2
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_autogen.h2
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h7
-rw-r--r--gpu/command_buffer/cmd_buffer_functions.txt3
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h2
-rw-r--r--gpu/command_buffer/service/feature_info.cc1
-rw-r--r--gpu/command_buffer/service/gl_utils.h4
-rw-r--r--gpu/gpu.gyp1
-rw-r--r--gpu/gpu_common.gypi2
17 files changed, 500 insertions, 5 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 21a9290..33690bf 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1702,6 +1702,13 @@ _FUNCTION_INFO = {
'decoder_func': 'DoLinkProgram',
'impl_func': False,
},
+ 'MapBufferCHROMIUM': {
+ 'gen_cmd': False,
+ 'extension': True,
+ 'chromium': True,
+ 'client_test': False,
+ 'chromium': True,
+ },
'MapBufferSubDataCHROMIUM': {
'gen_cmd': False,
'extension': True,
@@ -1924,6 +1931,13 @@ _FUNCTION_INFO = {
'count': 16,
'decoder_func': 'DoUniformMatrix4fv',
},
+ 'UnmapBufferCHROMIUM': {
+ 'gen_cmd': False,
+ 'extension': True,
+ 'chromium': True,
+ 'client_test': False,
+ 'chromium': True,
+ },
'UnmapBufferSubDataCHROMIUM': {
'gen_cmd': False,
'extension': True,
diff --git a/gpu/command_buffer/client/buffer_tracker.cc b/gpu/command_buffer/client/buffer_tracker.cc
new file mode 100644
index 0000000..3e4e087
--- /dev/null
+++ b/gpu/command_buffer/client/buffer_tracker.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2012 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 "../client/buffer_tracker.h"
+
+#include "../client/atomicops.h"
+#include "../client/cmd_buffer_helper.h"
+#include "../client/mapped_memory.h"
+
+namespace gpu {
+namespace gles2 {
+
+BufferTracker::BufferTracker(MappedMemoryManager* manager)
+ : mapped_memory_(manager) {
+}
+
+BufferTracker::~BufferTracker() {
+ while (!buffers_.empty()) {
+ RemoveBuffer(buffers_.begin()->first);
+ }
+}
+
+BufferTracker::Buffer* BufferTracker::CreateBuffer(
+ GLuint id, GLsizeiptr size) {
+ GPU_DCHECK_NE(0u, id);
+ GPU_DCHECK_LT(0, size);
+ int32 shm_id;
+ uint32 shm_offset;
+ void* address = mapped_memory_->Alloc(size, &shm_id, &shm_offset);
+ if (!address) {
+ return NULL;
+ }
+
+ Buffer* buffer = new Buffer(id, size, shm_id, shm_offset, address);
+ std::pair<BufferMap::iterator, bool> result =
+ buffers_.insert(std::make_pair(id, buffer));
+ GPU_DCHECK(result.second);
+ return buffer;
+}
+
+BufferTracker::Buffer* BufferTracker::GetBuffer(GLuint client_id) {
+ BufferMap::iterator it = buffers_.find(client_id);
+ return it != buffers_.end() ? it->second : NULL;
+}
+
+void BufferTracker::RemoveBuffer(GLuint client_id) {
+ BufferMap::iterator it = buffers_.find(client_id);
+ if (it != buffers_.end()) {
+ Buffer* buffer = it->second;
+ buffers_.erase(it);
+ if (buffer->address_)
+ mapped_memory_->Free(buffer->address_);
+ delete buffer;
+ }
+}
+
+void BufferTracker::FreePendingToken(Buffer* buffer, int32 token) {
+ GPU_DCHECK(buffer->address_);
+ mapped_memory_->FreePendingToken(buffer->address_, token);
+ buffer->size_ = 0;
+ buffer->shm_id_ = 0;
+ buffer->shm_offset_ = 0;
+ buffer->address_ = NULL;
+}
+
+
+} // namespace gles2
+} // namespace gpu
diff --git a/gpu/command_buffer/client/buffer_tracker.h b/gpu/command_buffer/client/buffer_tracker.h
new file mode 100644
index 0000000..54f5bc7
--- /dev/null
+++ b/gpu/command_buffer/client/buffer_tracker.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2012 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.
+
+#ifndef GPU_COMMAND_BUFFER_CLIENT_BUFFER_TRACKER_H_
+#define GPU_COMMAND_BUFFER_CLIENT_BUFFER_TRACKER_H_
+
+#include <GLES2/gl2.h>
+
+#include <queue>
+#include "../client/hash_tables.h"
+#include "../common/gles2_cmd_format.h"
+#include "gles2_impl_export.h"
+
+namespace gpu {
+
+class CommandBufferHelper;
+class MappedMemoryManager;
+
+namespace gles2 {
+
+// Tracks buffer objects for client side of command buffer.
+class GLES2_IMPL_EXPORT BufferTracker {
+ public:
+ class GLES2_IMPL_EXPORT Buffer {
+ public:
+ Buffer(GLuint id,
+ unsigned int size,
+ int32 shm_id,
+ uint32 shm_offset,
+ void* address)
+ : id_(id),
+ size_(size),
+ shm_id_(shm_id),
+ shm_offset_(shm_offset),
+ address_(address),
+ mapped_(false) {
+ }
+
+ GLenum id() const {
+ return id_;
+ }
+
+ unsigned int size() const {
+ return size_;
+ }
+
+ int32 shm_id() const {
+ return shm_id_;
+ }
+
+ uint32 shm_offset() const {
+ return shm_offset_;
+ }
+
+ void* address() const {
+ return address_;
+ }
+
+ void set_mapped(bool mapped) {
+ mapped_ = mapped;
+ }
+
+ bool mapped() const {
+ return mapped_;
+ }
+
+ private:
+ friend class BufferTracker;
+ friend class BufferTrackerTest;
+
+ GLuint id_;
+ unsigned int size_;
+ int32 shm_id_;
+ uint32 shm_offset_;
+ void* address_;
+ bool mapped_;
+ };
+
+ BufferTracker(MappedMemoryManager* manager);
+ ~BufferTracker();
+
+ Buffer* CreateBuffer(GLuint id, GLsizeiptr size);
+ Buffer* GetBuffer(GLuint id);
+ void RemoveBuffer(GLuint id);
+
+ // Frees the block of memory associated with buffer, pending the passage
+ // of a token.
+ void FreePendingToken(Buffer*, int32 token);
+
+ private:
+ typedef gpu::hash_map<GLuint, Buffer*> BufferMap;
+
+ MappedMemoryManager* mapped_memory_;
+ BufferMap buffers_;
+
+ DISALLOW_COPY_AND_ASSIGN(BufferTracker);
+};
+
+} // namespace gles2
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_CLIENT_BUFFER_TRACKER_H_
diff --git a/gpu/command_buffer/client/buffer_tracker_unittest.cc b/gpu/command_buffer/client/buffer_tracker_unittest.cc
new file mode 100644
index 0000000..b1a459c
--- /dev/null
+++ b/gpu/command_buffer/client/buffer_tracker_unittest.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2012 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.
+
+// Tests for the BufferTracker.
+
+#include "gpu/command_buffer/client/buffer_tracker.h"
+
+#include <GLES2/gl2ext.h>
+#include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/client/client_test_helper.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/mapped_memory.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+namespace gles2 {
+
+class BufferTrackerTest : public testing::Test {
+ protected:
+ static const int32 kNumCommandEntries = 400;
+ static const int32 kCommandBufferSizeBytes =
+ kNumCommandEntries * sizeof(CommandBufferEntry);
+
+ virtual void SetUp() {
+ command_buffer_.reset(new MockClientCommandBuffer());
+ helper_.reset(new GLES2CmdHelper(command_buffer_.get()));
+ helper_->Initialize(kCommandBufferSizeBytes);
+ mapped_memory_.reset(new MappedMemoryManager(helper_.get()));
+ buffer_tracker_.reset(new BufferTracker(mapped_memory_.get()));
+ }
+
+ virtual void TearDown() {
+ buffer_tracker_.reset();
+ mapped_memory_.reset();
+ helper_.reset();
+ command_buffer_.reset();
+ }
+
+ scoped_ptr<CommandBuffer> command_buffer_;
+ scoped_ptr<GLES2CmdHelper> helper_;
+ scoped_ptr<MappedMemoryManager> mapped_memory_;
+ scoped_ptr<BufferTracker> buffer_tracker_;
+};
+
+TEST_F(BufferTrackerTest, Basic) {
+ const GLuint kId1 = 123;
+ const GLuint kId2 = 124;
+ const GLsizeiptr size = 64;
+
+ // Check we can create a Buffer.
+ BufferTracker::Buffer* buffer = buffer_tracker_->CreateBuffer(kId1, size);
+ ASSERT_TRUE(buffer != NULL);
+ // Check we can get the same Buffer.
+ EXPECT_EQ(buffer, buffer_tracker_->GetBuffer(kId1));
+ // Check mapped memory address.
+ EXPECT_TRUE(buffer->address() != NULL);
+ // Check shared memory was allocated.
+ EXPECT_EQ(1lu, mapped_memory_->num_chunks());
+ // Check we get nothing for a non-existent buffer.
+ EXPECT_TRUE(buffer_tracker_->GetBuffer(kId2) == NULL);
+ // Check we can delete the buffer.
+ buffer_tracker_->RemoveBuffer(kId1);
+ // Check shared memory was freed.
+ mapped_memory_->FreeUnused();
+ EXPECT_EQ(0lu, mapped_memory_->num_chunks());
+ // Check we get nothing for a non-existent buffer.
+ EXPECT_TRUE(buffer_tracker_->GetBuffer(kId1) == NULL);
+}
+
+} // namespace gles2
+} // namespace gpu
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index bcc2f6a..6e760c9 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -588,6 +588,12 @@ void GLES2RegisterSharedIdsCHROMIUM(
GLboolean GLES2EnableFeatureCHROMIUM(const char* feature) {
return gles2::GetGLContext()->EnableFeatureCHROMIUM(feature);
}
+void* GLES2MapBufferCHROMIUM(GLuint target, GLenum access) {
+ return gles2::GetGLContext()->MapBufferCHROMIUM(target, access);
+}
+GLboolean GLES2UnmapBufferCHROMIUM(GLuint target) {
+ return gles2::GetGLContext()->UnmapBufferCHROMIUM(target);
+}
void* GLES2MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) {
return gles2::GetGLContext()->MapBufferSubDataCHROMIUM(
@@ -962,6 +968,10 @@ NameToFunc g_gles2_function_table[] = {
glRegisterSharedIdsCHROMIUM), },
{ "glEnableFeatureCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
glEnableFeatureCHROMIUM), },
+ { "glMapBufferCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
+ glMapBufferCHROMIUM), },
+ { "glUnmapBufferCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
+ glUnmapBufferCHROMIUM), },
{ "glMapBufferSubDataCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
glMapBufferSubDataCHROMIUM), },
{ "glUnmapBufferSubDataCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index b0b228d..43b88a0 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <string.h>
#include <GLES2/gl2ext.h>
+#include "../client/buffer_tracker.h"
#include "../client/mapped_memory.h"
#include "../client/program_info_manager.h"
#include "../client/query_tracker.h"
@@ -439,6 +440,7 @@ GLES2Implementation::GLES2Implementation(
bound_renderbuffer_(0),
bound_array_buffer_id_(0),
bound_element_array_buffer_id_(0),
+ bound_pixel_unpack_transfer_buffer_id_(0),
client_side_array_id_(0),
client_side_element_array_id_(0),
bound_vertex_array_id_(0),
@@ -515,6 +517,7 @@ bool GLES2Implementation::Initialize(
new TextureUnit[gl_state_.int_state.max_combined_texture_image_units]);
query_tracker_.reset(new QueryTracker(mapped_memory_.get()));
+ buffer_tracker_.reset(new BufferTracker(mapped_memory_.get()));
#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
GetIdHandler(id_namespaces::kBuffers)->MakeIds(
@@ -540,6 +543,8 @@ GLES2Implementation::~GLES2Implementation() {
#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]);
#endif
+ buffer_tracker_.reset();
+
// The share group needs to be able to use a command buffer to talk
// to service if it's destroyed so set one for it then release the reference.
// If it's destroyed it will use this GLES2Implemenation.
@@ -960,6 +965,9 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) {
return true;
}
return false;
+ case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM:
+ *params = bound_pixel_unpack_transfer_buffer_id_;
+ return true;
case GL_ACTIVE_TEXTURE:
*params = active_texture_unit_ + GL_TEXTURE0;
return true;
@@ -1612,6 +1620,30 @@ void GLES2Implementation::BufferDataHelper(
return;
}
+ if (target == GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM) {
+ GLuint buffer_id = bound_pixel_unpack_transfer_buffer_id_;
+ if (!buffer_id) {
+ SetGLError(GL_INVALID_VALUE, "glBufferData", "unknown buffer");
+ return;
+ }
+
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
+ if (buffer) {
+ // Free buffer memory, pending the passage of a token.
+ buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken());
+
+ // Remove old buffer.
+ buffer_tracker_->RemoveBuffer(buffer_id);
+ }
+
+ // Create new buffer.
+ buffer = buffer_tracker_->CreateBuffer(buffer_id, size);
+ GPU_DCHECK(buffer);
+ if (data)
+ memcpy(buffer->address(), data, size);
+ return;
+ }
+
// If there is no data just send BufferData
if (!data) {
helper_->BufferData(target, size, 0, 0, usage);
@@ -1662,6 +1694,26 @@ void GLES2Implementation::BufferSubDataHelper(
return;
}
+ if (target == GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM) {
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(
+ bound_pixel_unpack_transfer_buffer_id_);
+ if (!buffer) {
+ SetGLError(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
+ return;
+ }
+
+ int32 end = 0;
+ int32 buffer_size = buffer->size();
+ if (!SafeAddInt32(offset, size, &end) || end > buffer_size) {
+ SetGLError(GL_INVALID_VALUE, "glBufferSubData", "out of range");
+ return;
+ }
+
+ if (data)
+ memcpy(static_cast<uint8*>(buffer->address()) + offset, data, size);
+ return;
+ }
+
ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
BufferSubDataHelperImpl(target, offset, size, data, &buffer);
}
@@ -1700,6 +1752,27 @@ void GLES2Implementation::BufferSubData(
BufferSubDataHelper(target, offset, size, data);
}
+BufferTracker::Buffer*
+GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
+ const char* function_name, GLuint offset, GLsizei size)
+{
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(
+ bound_pixel_unpack_transfer_buffer_id_);
+ if (!buffer) {
+ SetGLError(GL_INVALID_OPERATION, function_name, "invalid buffer");
+ return NULL;
+ }
+ if (buffer->mapped()) {
+ SetGLError(GL_INVALID_OPERATION, function_name, "buffer mapped");
+ return NULL;
+ }
+ if ((buffer->size() - offset) < static_cast<GLuint>(size)) {
+ SetGLError(GL_INVALID_VALUE, function_name, "unpack size to large");
+ return NULL;
+ }
+ return buffer;
+}
+
void GLES2Implementation::CompressedTexImage2D(
GLenum target, GLint level, GLenum internalformat, GLsizei width,
GLsizei height, GLint border, GLsizei image_size, const void* data) {
@@ -1718,6 +1791,18 @@ void GLES2Implementation::CompressedTexImage2D(
if (height == 0 || width == 0) {
return;
}
+ // If there's a pixel unpack buffer bound use it when issuing
+ // CompressedTexImage2D.
+ if (bound_pixel_unpack_transfer_buffer_id_) {
+ GLuint offset = ToGLuint(data);
+ BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ "glCompressedTexImage2D", offset, image_size);
+ if (buffer)
+ helper_->CompressedTexImage2D(
+ target, level, internalformat, width, height, border, image_size,
+ buffer->shm_id(), buffer->shm_offset() + offset);
+ return;
+ }
SetBucketContents(kResultBucketId, data, image_size);
helper_->CompressedTexImage2DBucket(
target, level, internalformat, width, height, border, kResultBucketId);
@@ -1743,6 +1828,18 @@ void GLES2Implementation::CompressedTexSubImage2D(
SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "dimension < 0");
return;
}
+ // If there's a pixel unpack buffer bound use it when issuing
+ // CompressedTexSubImage2D.
+ if (bound_pixel_unpack_transfer_buffer_id_) {
+ GLuint offset = ToGLuint(data);
+ BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ "glCompressedTexSubImage2D", offset, image_size);
+ if (buffer)
+ helper_->CompressedTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, image_size,
+ buffer->shm_id(), buffer->shm_offset() + offset);
+ return;
+ }
SetBucketContents(kResultBucketId, data, image_size);
helper_->CompressedTexSubImage2DBucket(
target, level, xoffset, yoffset, width, height, format, kResultBucketId);
@@ -1814,6 +1911,18 @@ void GLES2Implementation::TexImage2D(
return;
}
+ // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
+ if (bound_pixel_unpack_transfer_buffer_id_) {
+ GLuint offset = ToGLuint(pixels);
+ BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ "glTexImage2D", offset, size);
+ if (buffer)
+ helper_->TexImage2D(
+ target, level, internalformat, width, height, border, format, type,
+ buffer->shm_id(), buffer->shm_offset() + offset);
+ return;
+ }
+
// If there's no data just issue TexImage2D
if (!pixels) {
helper_->TexImage2D(
@@ -1901,6 +2010,18 @@ void GLES2Implementation::TexSubImage2D(
return;
}
+ // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
+ if (bound_pixel_unpack_transfer_buffer_id_) {
+ GLuint offset = ToGLuint(pixels);
+ BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ "glTexSubImage2D", offset, temp_size);
+ if (buffer)
+ helper_->TexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, type,
+ buffer->shm_id(), buffer->shm_offset() + offset, false);
+ return;
+ }
+
// compute the advance bytes per row for the src pixels
uint32 src_padded_row_size;
if (unpack_row_length_ > 0) {
@@ -2417,6 +2538,9 @@ void GLES2Implementation::BindBufferHelper(
case GL_ELEMENT_ARRAY_BUFFER:
bound_element_array_buffer_id_ = buffer;
break;
+ case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
+ bound_pixel_unpack_transfer_buffer_id_ = buffer;
+ break;
default:
break;
}
@@ -2511,6 +2635,17 @@ void GLES2Implementation::DeleteBuffersHelper(
if (buffers[ii] == bound_element_array_buffer_id_) {
bound_element_array_buffer_id_ = 0;
}
+ if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) {
+ bound_pixel_unpack_transfer_buffer_id_ = 0;
+ }
+
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]);
+ if (buffer) {
+ // Free buffer memory, pending the passage of a token.
+ buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken());
+ // Remove buffer.
+ buffer_tracker_->RemoveBuffer(buffers[ii]);
+ }
}
}
@@ -3480,6 +3615,59 @@ void GLES2Implementation::TraceBeginCHROMIUM(const char* name) {
helper_->SetBucketSize(kResultBucketId, 0);
}
+void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
+ << target << ", " << GLES2Util::GetStringEnum(access) << ")");
+ if (target != GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM) {
+ SetGLError(
+ GL_INVALID_ENUM, "glMapBufferCHROMIUM", "invalid target");
+ return NULL;
+ }
+ if (access != GL_WRITE_ONLY) {
+ SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode");
+ return NULL;
+ }
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(
+ bound_pixel_unpack_transfer_buffer_id_);
+ if (!buffer) {
+ SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer");
+ return NULL;
+ }
+ if (buffer->mapped()) {
+ SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped");
+ return NULL;
+ }
+ buffer->set_mapped(true);
+
+ GPU_DCHECK(buffer->address());
+ GPU_CLIENT_LOG(" returned " << buffer->address());
+ return buffer->address();
+}
+
+GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG(
+ "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target << ")");
+ if (target != GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM) {
+ SetGLError(GL_INVALID_ENUM, "glUnmapBufferCHROMIUM", "invalid target");
+ return false;
+ }
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(
+ bound_pixel_unpack_transfer_buffer_id_);
+ if (!buffer) {
+ SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer");
+ return false;
+ }
+ if (!buffer->mapped()) {
+ SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "not mapped");
+ return false;
+ }
+ buffer->set_mapped(false);
+
+ return true;
+}
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 47fb3b0..47c221c 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -13,16 +13,17 @@
#include <string>
#include <vector>
-#include "../common/compiler_specific.h"
-#include "../common/debug_marker_manager.h"
-#include "../common/gles2_cmd_utils.h"
-#include "../common/scoped_ptr.h"
-#include "../client/ref_counted.h"
+#include "../client/buffer_tracker.h"
#include "../client/gles2_cmd_helper.h"
#include "../client/gles2_interface.h"
#include "../client/query_tracker.h"
+#include "../client/ref_counted.h"
#include "../client/ring_buffer.h"
#include "../client/share_group.h"
+#include "../common/compiler_specific.h"
+#include "../common/debug_marker_manager.h"
+#include "../common/gles2_cmd_utils.h"
+#include "../common/scoped_ptr.h"
#include "gles2_impl_export.h"
#if !defined(NDEBUG) && !defined(__native_client__) && !defined(GLES2_CONFORMANCE_TESTS) // NOLINT
@@ -483,6 +484,9 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface {
// for error checking.
bool MustBeContextLost();
+ BufferTracker::Buffer* GetBoundPixelUnpackTransferBufferIfValid(
+ const char* function_name, GLuint offset, GLsizei size);
+
const std::string& GetLogPrefix() const;
GLES2Util util_;
@@ -534,6 +538,9 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface {
// The currently bound element array buffer.
GLuint bound_element_array_buffer_id_;
+ // The currently bound pixel transfer buffer.
+ GLuint bound_pixel_unpack_transfer_buffer_id_;
+
// GL names for the buffers used to emulate client side buffers.
GLuint client_side_array_id_;
GLuint client_side_element_array_id_;
@@ -578,6 +585,8 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface {
scoped_ptr<QueryTracker> query_tracker_;
QueryTracker::Query* current_query_;
+ scoped_ptr<BufferTracker> buffer_tracker_;
+
ErrorMessageCallback* error_message_callback_;
DISALLOW_COPY_AND_ASSIGN(GLES2Implementation);
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 0034ba3..b6dce8c 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -434,6 +434,10 @@ virtual void RegisterSharedIdsCHROMIUM(
virtual GLboolean EnableFeatureCHROMIUM(const char* feature) OVERRIDE;
+virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) OVERRIDE;
+
+virtual GLboolean UnmapBufferCHROMIUM(GLuint target) OVERRIDE;
+
virtual void* MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) OVERRIDE;
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index 3879fe11..b83bad5 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -248,6 +248,8 @@ virtual void DeleteSharedIdsCHROMIUM(
virtual void RegisterSharedIdsCHROMIUM(
GLuint namespace_id, GLsizei n, const GLuint* ids) = 0;
virtual GLboolean EnableFeatureCHROMIUM(const char* feature) = 0;
+virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) = 0;
+virtual GLboolean UnmapBufferCHROMIUM(GLuint target) = 0;
virtual void* MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) = 0;
virtual void UnmapBufferSubDataCHROMIUM(const void* mem) = 0;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 5ea0131..452b4c7 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -277,6 +277,8 @@ virtual void DeleteSharedIdsCHROMIUM(
virtual void RegisterSharedIdsCHROMIUM(
GLuint namespace_id, GLsizei n, const GLuint* ids) OVERRIDE;
virtual GLboolean EnableFeatureCHROMIUM(const char* feature) OVERRIDE;
+virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) OVERRIDE;
+virtual GLboolean UnmapBufferCHROMIUM(GLuint target) OVERRIDE;
virtual void* MapBufferSubDataCHROMIUM(
GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) OVERRIDE;
virtual void UnmapBufferSubDataCHROMIUM(const void* mem) OVERRIDE;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index 735ac0a..1cf7548 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -520,6 +520,13 @@ GLboolean GLES2InterfaceStub::EnableFeatureCHROMIUM(
const char* /* feature */) {
return 0;
}
+void* GLES2InterfaceStub::MapBufferCHROMIUM(
+ GLuint /* target */, GLenum /* access */) {
+ return 0;
+}
+GLboolean GLES2InterfaceStub::UnmapBufferCHROMIUM(GLuint /* target */) {
+ return 0;
+}
void* GLES2InterfaceStub::MapBufferSubDataCHROMIUM(
GLuint /* target */, GLintptr /* offset */, GLsizeiptr /* size */,
GLenum /* access */) {
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index a759cd0..a91f8db 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -173,6 +173,9 @@ GL_APICALL void GL_APIENTRY glGenSharedIdsCHROMIUM (GLuint namespace_id,
GL_APICALL void GL_APIENTRY glDeleteSharedIdsCHROMIUM (GLuint namespace_id, GLsizeiNotNegative n, const GLuint* ids);
GL_APICALL void GL_APIENTRY glRegisterSharedIdsCHROMIUM (GLuint namespace_id, GLsizeiNotNegative n, const GLuint* ids);
GL_APICALL GLboolean GL_APIENTRY glEnableFeatureCHROMIUM (const char* feature);
+GL_APICALL void* GL_APIENTRY glMapBufferCHROMIUM (GLuint target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferCHROMIUM (GLuint target);
+
GL_APICALL void* GL_APIENTRY glMapBufferSubDataCHROMIUM (GLuint target, GLintptrNotNegative offset, GLsizeiptr size, GLenum access);
GL_APICALL void GL_APIENTRY glUnmapBufferSubDataCHROMIUM (const void* mem);
GL_APICALL void* GL_APIENTRY glMapTexSubImage2DCHROMIUM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum access);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index 901f52a..03913b4 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -550,6 +550,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = {
{ 0x80C9, "GL_BLEND_SRC_RGB", },
{ 0x80C8, "GL_BLEND_DST_RGB", },
{ 0x0504, "GL_STACK_UNDERFLOW", },
+ { 0x88EC, "GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM", },
{ 0x8059, "GL_RGB10_A2_EXT", },
{ 0x8058, "GL_RGBA8_OES", },
{ 0x00002000, "GL_DEPTH_BUFFER_BIT5_QCOM", },
@@ -634,6 +635,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = {
{ 0x8CAA, "GL_READ_FRAMEBUFFER_BINDING_ANGLE", },
{ 0x40000000, "GL_MULTISAMPLE_BUFFER_BIT6_QCOM", },
{ 0x9116, "GL_SYNC_FENCE_APPLE", },
+ { 0x88EF, "GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM", },
{ 0x00000800, "GL_DEPTH_BUFFER_BIT3_QCOM", },
{ 0x1903, "GL_RED_EXT", },
{ 0x8CE2, "GL_COLOR_ATTACHMENT2_NV", },
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 7283ac2..3c2365e 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -241,6 +241,7 @@ void FeatureInfo::AddFeatures(const char* desired_features) {
AddExtensionString("GL_CHROMIUM_copy_texture");
AddExtensionString("GL_CHROMIUM_discard_framebuffer");
AddExtensionString("GL_CHROMIUM_get_error_query");
+ AddExtensionString("GL_CHROMIUM_pixel_transfer_buffer_object");
AddExtensionString("GL_CHROMIUM_rate_limit_offscreen_context");
AddExtensionString("GL_CHROMIUM_resize");
AddExtensionString("GL_CHROMIUM_resource_safe");
diff --git a/gpu/command_buffer/service/gl_utils.h b/gpu/command_buffer/service/gl_utils.h
index bd3ca49..ccd96f3 100644
--- a/gpu/command_buffer/service/gl_utils.h
+++ b/gpu/command_buffer/service/gl_utils.h
@@ -110,6 +110,10 @@
// GL_OES_vertex_array_object
#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+// GL_CHROMIUM_pixel_transfer_buffer_object
+#define GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM 0x78EC
+#define GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM 0x78EF
+
#define GL_GLEXT_PROTOTYPES 1
// GL_ARB_get_program_binary
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 39feafa..ff0717b 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -130,6 +130,7 @@
],
'sources': [
'<@(gles2_c_lib_source_files)',
+ 'command_buffer/client/buffer_tracker_unittest.cc',
'command_buffer/client/client_test_helper.cc',
'command_buffer/client/client_test_helper.h',
'command_buffer/client/cmd_buffer_helper_test.cc',
diff --git a/gpu/gpu_common.gypi b/gpu/gpu_common.gypi
index 24c7e4d..98fb3c1 100644
--- a/gpu/gpu_common.gypi
+++ b/gpu/gpu_common.gypi
@@ -19,6 +19,8 @@
# with without support for client side arrays and once with for pepper and
# the OpenGL ES 2.0 compliant for the conformance tests.
'gles2_implementation_source_files': [
+ 'command_buffer/client/buffer_tracker.cc',
+ 'command_buffer/client/buffer_tracker.h',
'command_buffer/client/gles2_impl_export.h',
'command_buffer/client/gles2_implementation_autogen.h',
'command_buffer/client/gles2_implementation.cc',