summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordyen <dyen@chromium.org>2016-01-05 16:50:16 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-06 00:52:09 +0000
commit882d69d97b5c43b7579bc610722dbadd328ac63e (patch)
tree5fb8f5f9fcf3e4d81600f90579fcbf9e274714fc
parent7fbe484c9fff54d9fd536a3a762b2bcfa9ad782e (diff)
downloadchromium_src-882d69d97b5c43b7579bc610722dbadd328ac63e.zip
chromium_src-882d69d97b5c43b7579bc610722dbadd328ac63e.tar.gz
chromium_src-882d69d97b5c43b7579bc610722dbadd328ac63e.tar.bz2
Verify resource provider sync tokens before sending to parent.
R=piman@chromium.org BUG=514815 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1479673003 Cr-Commit-Position: refs/heads/master@{#367727}
-rw-r--r--cc/resources/resource_provider.cc26
-rw-r--r--cc/resources/resource_provider_unittest.cc110
-rw-r--r--cc/test/test_gles2_interface.cc19
-rw-r--r--cc/test/test_gles2_interface.h6
-rw-r--r--cc/test/test_web_graphics_context_3d.cc28
-rw-r--r--cc/test/test_web_graphics_context_3d.h7
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc32
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc70
8 files changed, 239 insertions, 59 deletions
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index c6e5c91..f1a4cf2 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -1140,6 +1140,9 @@ void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
DCHECK(thread_checker_.CalledOnValidThread());
GLES2Interface* gl = ContextGL();
bool need_sync_token = false;
+
+ gpu::SyncToken new_sync_token;
+ std::vector<GLbyte*> unverified_sync_tokens;
for (ResourceIdArray::const_iterator it = resources.begin();
it != resources.end();
++it) {
@@ -1147,17 +1150,36 @@ void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
TransferResource(gl, *it, &resource);
need_sync_token |= (!resource.mailbox_holder.sync_token.HasData() &&
!resource.is_software);
+
+ if (resource.mailbox_holder.sync_token.HasData() &&
+ !resource.mailbox_holder.sync_token.verified_flush()) {
+ unverified_sync_tokens.push_back(
+ resource.mailbox_holder.sync_token.GetData());
+ }
+
++resources_.find(*it)->second.exported_count;
list->push_back(resource);
}
+
if (need_sync_token &&
output_surface_->capabilities().delegated_sync_points_required) {
- gpu::SyncToken sync_token(gl->InsertSyncPointCHROMIUM());
+ const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
+ gl->OrderingBarrierCHROMIUM();
+ gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData());
+ unverified_sync_tokens.push_back(new_sync_token.GetData());
+ }
+
+ if (!unverified_sync_tokens.empty()) {
+ gl->VerifySyncTokensCHROMIUM(unverified_sync_tokens.data(),
+ unverified_sync_tokens.size());
+ }
+
+ if (new_sync_token.HasData()) {
for (TransferableResourceArray::iterator it = list->begin();
it != list->end();
++it) {
if (!it->mailbox_holder.sync_token.HasData())
- it->mailbox_holder.sync_token = sync_token;
+ it->mailbox_holder.sync_token = new_sync_token;
}
}
}
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index 3374e85..1a0e685 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -39,7 +39,6 @@
using testing::Mock;
using testing::NiceMock;
using testing::Return;
-using testing::SetArgPointee;
using testing::StrictMock;
using testing::_;
@@ -104,7 +103,6 @@ class TextureStateTrackingContext : public TestWebGraphicsContext3D {
MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token));
- MOCK_METHOD0(insertSyncPoint, GLuint(void));
MOCK_METHOD3(produceTextureDirectCHROMIUM,
void(GLuint texture, GLenum target, const GLbyte* mailbox));
MOCK_METHOD2(createAndConsumeTextureCHROMIUM,
@@ -116,7 +114,21 @@ class TextureStateTrackingContext : public TestWebGraphicsContext3D {
base::AutoLock lock(namespace_->lock);
return namespace_->next_texture_id++;
}
+
void RetireTextureId(GLuint) override {}
+
+ GLuint64 insertFenceSync() override { return next_fence_sync_++; }
+
+ void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token) override {
+ gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0,
+ 0x123, fence_sync);
+ sync_token_data.SetVerifyFlush();
+ memcpy(sync_token, &sync_token_data, sizeof(sync_token_data));
+ }
+
+ GLuint64 GetNextFenceSync() const { return next_fence_sync_; }
+
+ GLuint64 next_fence_sync_ = 1;
};
// Shared data between multiple ResourceProviderContext. This contains mailbox
@@ -127,7 +139,7 @@ class ContextSharedData {
return make_scoped_ptr(new ContextSharedData());
}
- uint32_t InsertSyncPoint() { return next_sync_point_++; }
+ uint32_t InsertFenceSync() { return next_fence_sync_++; }
void GenMailbox(GLbyte* mailbox) {
memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
@@ -165,9 +177,9 @@ class ContextSharedData {
}
private:
- ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
+ ContextSharedData() : next_fence_sync_(1), next_mailbox_(1) {}
- uint32_t next_sync_point_;
+ uint64_t next_fence_sync_;
unsigned next_mailbox_;
typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap;
TextureMap textures_;
@@ -182,19 +194,40 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
}
GLuint insertSyncPoint() override {
- uint32_t sync_point = shared_data_->InsertSyncPoint();
+ const uint32_t sync_point =
+ static_cast<uint32_t>(shared_data_->InsertFenceSync());
+ gpu::SyncToken sync_token_data(sync_point);
+
// Commit the produceTextureCHROMIUM calls at this point, so that
// they're associated with the sync point.
for (const scoped_ptr<PendingProduceTexture>& pending_texture :
pending_produce_textures_) {
- shared_data_->ProduceTexture(pending_texture->mailbox,
- gpu::SyncToken(sync_point),
+ shared_data_->ProduceTexture(pending_texture->mailbox, sync_token_data,
pending_texture->texture);
}
pending_produce_textures_.clear();
return sync_point;
}
+ GLuint64 insertFenceSync() override {
+ return shared_data_->InsertFenceSync();
+ }
+
+ void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token) override {
+ gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0,
+ 0x123, fence_sync);
+ sync_token_data.SetVerifyFlush();
+ // Commit the produceTextureCHROMIUM calls at this point, so that
+ // they're associated with the sync point.
+ for (const scoped_ptr<PendingProduceTexture>& pending_texture :
+ pending_produce_textures_) {
+ shared_data_->ProduceTexture(pending_texture->mailbox, sync_token_data,
+ pending_texture->texture);
+ }
+ pending_produce_textures_.clear();
+ memcpy(sync_token, &sync_token_data, sizeof(sync_token_data));
+ }
+
void waitSyncToken(const GLbyte* sync_token) override {
gpu::SyncToken sync_token_data;
if (sync_token)
@@ -280,7 +313,7 @@ class ResourceProviderContext : public TestWebGraphicsContext3D {
GLenum target,
const GLbyte* mailbox) override {
// Delay moving the texture into the mailbox until the next
- // InsertSyncPoint, so that it is not visible to other contexts that
+ // sync token, so that it is not visible to other contexts that
// haven't waited on that sync point.
scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
@@ -477,7 +510,8 @@ class ResourceProviderTest
child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D,
gpu_mailbox.name);
- *sync_token = gpu::SyncToken(child_context_->insertSyncPoint());
+ child_context_->genSyncToken(child_context_->insertFenceSync(),
+ sync_token->GetData());
EXPECT_TRUE(sync_token->HasData());
scoped_ptr<SharedBitmap> shared_bitmap;
@@ -633,7 +667,10 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
child_context_->genMailboxCHROMIUM(external_mailbox.name);
child_context_->produceTextureDirectCHROMIUM(
external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
- const gpu::SyncToken external_sync_token(child_context_->insertSyncPoint());
+ gpu::SyncToken external_sync_token;
+ child_context_->genSyncToken(child_context_->insertFenceSync(),
+ external_sync_token.GetData());
+ EXPECT_TRUE(external_sync_token.HasData());
ResourceId id4 = child_resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(external_mailbox, external_sync_token,
GL_TEXTURE_EXTERNAL_OES),
@@ -889,7 +926,10 @@ TEST_P(ResourceProviderTestNoSyncToken, TransferGLResources) {
child_context_->genMailboxCHROMIUM(external_mailbox.name);
child_context_->produceTextureDirectCHROMIUM(
external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
- const gpu::SyncToken external_sync_token(child_context_->insertSyncPoint());
+ gpu::SyncToken external_sync_token;
+ child_context_->genSyncToken(child_context_->insertFenceSync(),
+ external_sync_token.GetData());
+ EXPECT_TRUE(external_sync_token.HasData());
ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
TextureMailbox(external_mailbox, external_sync_token,
GL_TEXTURE_EXTERNAL_OES),
@@ -1961,7 +2001,6 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
EXPECT_CALL(*child_context,
produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
- EXPECT_CALL(*child_context, insertSyncPoint());
child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
&list);
Mock::VerifyAndClearExpectations(child_context);
@@ -2019,7 +2058,6 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest {
// Transfer resources back from the parent to the child. Set no resources
// as being in use.
ResourceProvider::ResourceIdSet no_resources;
- EXPECT_CALL(*parent_context, insertSyncPoint());
parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
no_resources);
Mock::VerifyAndClearExpectations(parent_context);
@@ -2059,7 +2097,9 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
gpu::Mailbox mailbox;
context()->genMailboxCHROMIUM(mailbox.name);
context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
- gpu::SyncToken sync_token(context()->insertSyncPoint());
+ gpu::SyncToken sync_token;
+ context()->genSyncToken(context()->insertFenceSync(), sync_token.GetData());
+ EXPECT_TRUE(sync_token.HasData());
// All the logic below assumes that the sync token releases are all positive.
EXPECT_LT(0u, sync_token.release_count());
@@ -2101,8 +2141,9 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
mailbox.name);
context()->deleteTexture(other_texture);
- list[0].mailbox_holder.sync_token =
- gpu::SyncToken(context()->insertSyncPoint());
+ context()->genSyncToken(context()->insertFenceSync(),
+ list[0].mailbox_holder.sync_token.GetData());
+ EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
// Receive the resource, then delete it, expect the sync points to be
// consistent.
@@ -2155,9 +2196,9 @@ TEST_P(ResourceProviderTest, TransferMailboxResources) {
context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
mailbox.name);
context()->deleteTexture(other_texture);
- list[0].mailbox_holder.sync_token =
- gpu::SyncToken(context()->insertSyncPoint());
- EXPECT_LT(0u, list[0].mailbox_holder.sync_token.release_count());
+ context()->genSyncToken(context()->insertFenceSync(),
+ list[0].mailbox_holder.sync_token.GetData());
+ EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
// Delete the resource, which shouldn't do anything.
resource_provider_->DeleteResource(resource);
@@ -2490,7 +2531,8 @@ TEST_P(ResourceProviderTest, LostContext) {
gpu::Mailbox mailbox;
context()->genMailboxCHROMIUM(mailbox.name);
context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
- gpu::SyncToken sync_token(context()->insertSyncPoint());
+ gpu::SyncToken sync_token;
+ context()->genSyncToken(context()->insertFenceSync(), sync_token.GetData());
EXPECT_TRUE(sync_token.HasData());
@@ -2810,12 +2852,13 @@ class ResourceProviderTestTextureMailboxGLFilters
use_image_texture_targets_));
unsigned texture_id = 1;
- gpu::SyncToken sync_token(30);
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, 0x12,
+ 0x34);
unsigned target = GL_TEXTURE_2D;
+ const GLuint64 current_fence_sync = context->GetNextFenceSync();
EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
- EXPECT_CALL(*context, insertSyncPoint()).Times(0);
EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
@@ -2835,6 +2878,7 @@ class ResourceProviderTestTextureMailboxGLFilters
ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
mailbox, std::move(callback));
EXPECT_NE(0u, id);
+ EXPECT_EQ(current_fence_sync, context->GetNextFenceSync());
Mock::VerifyAndClearExpectations(context);
@@ -2848,7 +2892,6 @@ class ResourceProviderTestTextureMailboxGLFilters
.WillOnce(Return(texture_id));
EXPECT_CALL(*context, bindTexture(target, texture_id));
- EXPECT_CALL(*context, insertSyncPoint()).Times(0);
EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
// The sampler will reset these if |mailbox_nearest_neighbor| does not
@@ -2863,11 +2906,11 @@ class ResourceProviderTestTextureMailboxGLFilters
ResourceProvider::ScopedSamplerGL lock(
resource_provider.get(), id, sampler_filter);
Mock::VerifyAndClearExpectations(context);
+ EXPECT_EQ(current_fence_sync, context->GetNextFenceSync());
// When done with it, a sync point should be inserted, but no produce is
// necessary.
EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
- EXPECT_CALL(*context, insertSyncPoint());
EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
@@ -2875,7 +2918,7 @@ class ResourceProviderTestTextureMailboxGLFilters
}
resource_provider->DeleteResource(id);
- EXPECT_FALSE(release_sync_token.HasData());
+ EXPECT_TRUE(release_sync_token.HasData());
EXPECT_FALSE(lost_resource);
EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
}
@@ -2952,12 +2995,12 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
gpu_memory_buffer_manager_.get(), NULL, 0, 1,
use_gpu_memory_buffer_resources_, use_image_texture_targets_));
- gpu::SyncToken sync_token(30);
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, 0x12, 0x34);
+ const GLuint64 current_fence_sync = context->GetNextFenceSync();
unsigned target = GL_TEXTURE_EXTERNAL_OES;
EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
- EXPECT_CALL(*context, insertSyncPoint()).Times(0);
EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
@@ -2971,6 +3014,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
mailbox, std::move(callback));
EXPECT_NE(0u, id);
+ EXPECT_EQ(current_fence_sync, context->GetNextFenceSync());
Mock::VerifyAndClearExpectations(context);
@@ -2985,7 +3029,6 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
.WillOnce(Return(texture_id));
- EXPECT_CALL(*context, insertSyncPoint()).Times(0);
EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
@@ -2994,7 +3037,6 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
// When done with it, a sync point should be inserted, but no produce is
// necessary.
EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
- EXPECT_CALL(*context, insertSyncPoint());
EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
@@ -3022,12 +3064,12 @@ TEST_P(ResourceProviderTest,
gpu_memory_buffer_manager_.get(), NULL, 0, 1,
use_gpu_memory_buffer_resources_, use_image_texture_targets_));
- gpu::SyncToken sync_token(30);
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, 0x12, 0x34);
+ const GLuint64 current_fence_sync = context->GetNextFenceSync();
unsigned target = GL_TEXTURE_2D;
EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
- EXPECT_CALL(*context, insertSyncPoint()).Times(0);
EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
@@ -3041,6 +3083,7 @@ TEST_P(ResourceProviderTest,
ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
mailbox, std::move(callback));
EXPECT_NE(0u, id);
+ EXPECT_EQ(current_fence_sync, context->GetNextFenceSync());
Mock::VerifyAndClearExpectations(context);
@@ -3077,11 +3120,11 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncTokenIfNeeded_NoSyncToken) {
use_gpu_memory_buffer_resources_, use_image_texture_targets_));
gpu::SyncToken sync_token;
+ const GLuint64 current_fence_sync = context->GetNextFenceSync();
unsigned target = GL_TEXTURE_2D;
EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
- EXPECT_CALL(*context, insertSyncPoint()).Times(0);
EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
@@ -3095,6 +3138,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncTokenIfNeeded_NoSyncToken) {
ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
mailbox, std::move(callback));
EXPECT_NE(0u, id);
+ EXPECT_EQ(current_fence_sync, context->GetNextFenceSync());
Mock::VerifyAndClearExpectations(context);
diff --git a/cc/test/test_gles2_interface.cc b/cc/test/test_gles2_interface.cc
index 2781712..97766fb 100644
--- a/cc/test/test_gles2_interface.cc
+++ b/cc/test/test_gles2_interface.cc
@@ -327,6 +327,25 @@ GLuint TestGLES2Interface::InsertSyncPointCHROMIUM() {
return test_context_->insertSyncPoint();
}
+GLuint64 TestGLES2Interface::InsertFenceSyncCHROMIUM() {
+ return test_context_->insertFenceSync();
+}
+
+void TestGLES2Interface::GenSyncTokenCHROMIUM(GLuint64 fence_sync,
+ GLbyte* sync_token) {
+ test_context_->genSyncToken(fence_sync, sync_token);
+}
+
+void TestGLES2Interface::GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync,
+ GLbyte* sync_token) {
+ test_context_->genSyncToken(fence_sync, sync_token);
+}
+
+void TestGLES2Interface::VerifySyncTokensCHROMIUM(GLbyte** sync_tokens,
+ GLsizei count) {
+ test_context_->verifySyncTokens(sync_tokens, count);
+}
+
void TestGLES2Interface::WaitSyncTokenCHROMIUM(const GLbyte* sync_token) {
test_context_->waitSyncToken(sync_token);
}
diff --git a/cc/test/test_gles2_interface.h b/cc/test/test_gles2_interface.h
index 0914810..fe4f16f 100644
--- a/cc/test/test_gles2_interface.h
+++ b/cc/test/test_gles2_interface.h
@@ -138,7 +138,11 @@ class TestGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
GLenum usage) override;
GLuint InsertSyncPointCHROMIUM() override;
-
+ GLuint64 InsertFenceSyncCHROMIUM() override;
+ void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override;
+ void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync,
+ GLbyte* sync_token) override;
+ void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) override;
void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override;
void BeginQueryEXT(GLenum target, GLuint id) override;
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc
index 96b11b4..8e4df91 100644
--- a/cc/test/test_web_graphics_context_3d.cc
+++ b/cc/test/test_web_graphics_context_3d.cc
@@ -69,7 +69,7 @@ TestWebGraphicsContext3D::TestWebGraphicsContext3D()
scale_factor_(-1.f),
test_support_(NULL),
last_update_type_(NO_UPDATE),
- next_insert_sync_point_(1),
+ next_insert_fence_sync_(1),
unpack_alignment_(4),
bound_buffer_(0),
weak_ptr_factory_(this) {
@@ -649,8 +649,20 @@ GLuint TestWebGraphicsContext3D::createGpuMemoryBufferImageCHROMIUM(
return image_id;
}
-unsigned TestWebGraphicsContext3D::insertSyncPoint() {
- return next_insert_sync_point_++;
+GLuint TestWebGraphicsContext3D::insertSyncPoint() {
+ return static_cast<GLuint>(next_insert_fence_sync_++);
+}
+
+GLuint64 TestWebGraphicsContext3D::insertFenceSync() {
+ return next_insert_fence_sync_++;
+}
+
+void TestWebGraphicsContext3D::genSyncToken(GLuint64 fence_sync,
+ GLbyte* sync_token) {
+ gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0, 0,
+ fence_sync);
+ sync_token_data.SetVerifyFlush();
+ memcpy(sync_token, &sync_token_data, sizeof(sync_token_data));
}
void TestWebGraphicsContext3D::waitSyncToken(const GLbyte* sync_token) {
@@ -662,6 +674,16 @@ void TestWebGraphicsContext3D::waitSyncToken(const GLbyte* sync_token) {
}
}
+void TestWebGraphicsContext3D::verifySyncTokens(GLbyte** sync_tokens,
+ GLsizei count) {
+ for (GLsizei i = 0; i < count; ++i) {
+ gpu::SyncToken sync_token_data;
+ memcpy(sync_token_data.GetData(), sync_tokens[i], sizeof(sync_token_data));
+ sync_token_data.SetVerifyFlush();
+ memcpy(sync_tokens[i], &sync_token_data, sizeof(sync_token_data));
+ }
+}
+
size_t TestWebGraphicsContext3D::NumTextures() const {
base::AutoLock lock(namespace_->lock);
return namespace_->textures.Size();
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h
index 08447f7..fba2b8d 100644
--- a/cc/test/test_web_graphics_context_3d.h
+++ b/cc/test/test_web_graphics_context_3d.h
@@ -275,8 +275,11 @@ class TestWebGraphicsContext3D {
GLuint io_surface_id,
GLuint plane) {}
- virtual unsigned insertSyncPoint();
+ virtual GLuint insertSyncPoint();
+ virtual GLuint64 insertFenceSync();
+ virtual void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token);
virtual void waitSyncToken(const GLbyte* sync_token);
+ virtual void verifySyncTokens(GLbyte** sync_tokens, GLsizei count);
const gpu::SyncToken& last_waited_sync_token() const {
return last_waited_sync_token_;
@@ -482,7 +485,7 @@ class TestWebGraphicsContext3D {
TestContextSupport* test_support_;
gfx::Rect update_rect_;
UpdateType last_update_type_;
- unsigned next_insert_sync_point_;
+ GLuint64 next_insert_fence_sync_;
gpu::SyncToken last_waited_sync_token_;
int unpack_alignment_;
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 96d08e1..556eea7 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -5589,7 +5589,7 @@ void GLES2Implementation::GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync,
void GLES2Implementation::VerifySyncTokensCHROMIUM(GLbyte **sync_tokens,
GLsizei count) {
- bool sync_tokens_verified = false;
+ bool requires_synchronization = false;
for (GLsizei i = 0; i < count; ++i) {
if (sync_tokens[i]) {
SyncToken sync_token;
@@ -5601,18 +5601,26 @@ void GLES2Implementation::VerifySyncTokensCHROMIUM(GLbyte **sync_tokens,
"Cannot verify sync token using this context.");
return;
}
- if (!sync_tokens_verified) {
- // Insert a fence sync here and ensure it is received immediately.
- // This will require a flush but simplifies things a bit because
- // unverified sync tokens only need an ordering barrier.
- const uint64_t release = gpu_control_->GenerateFenceSyncRelease();
- FlushHelper();
- const bool verified = gpu_control_->IsFenceSyncFlushReceived(release);
- DCHECK(verified);
-
- sync_tokens_verified = true;
- }
+ requires_synchronization = true;
+ }
+ }
+ }
+
+ // This step must be done after all unverified tokens have finished processing
+ // CanWaitUnverifiedSyncToken(), command buffers use that to do any necessary
+ // flushes.
+ if (requires_synchronization) {
+ // Make sure we have no pending ordering barriers by flushing now.
+ FlushHelper();
+ // Ensure all the fence syncs are visible on GPU service.
+ gpu_control_->EnsureWorkVisible();
+
+ // We can automatically mark everything as verified now.
+ for (GLsizei i = 0; i < count; ++i) {
+ SyncToken sync_token;
+ memcpy(&sync_token, sync_tokens[i], sizeof(sync_token));
+ if (!sync_token.verified_flush()) {
sync_token.SetVerifyFlush();
memcpy(sync_tokens[i], &sync_token, sizeof(sync_token));
}
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 732107b..e408610 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -35,6 +35,7 @@ using testing::DoAll;
using testing::InSequence;
using testing::Invoke;
using testing::Mock;
+using testing::Pointee;
using testing::Sequence;
using testing::StrictMock;
using testing::Truly;
@@ -3881,14 +3882,10 @@ TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM) {
EXPECT_FALSE(sync_token.verified_flush());
ClearCommands();
- const GLuint64 kVerifyFenceSync = 234u;
EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(_))
.WillOnce(testing::Return(true));
- EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
- .WillOnce(testing::Return(kVerifyFenceSync));
- EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(kVerifyFenceSync))
- .WillOnce(testing::Return(true));
- gl_->VerifySyncTokensCHROMIUM(sync_token_datas, 1);
+ EXPECT_CALL(*gpu_control_, EnsureWorkVisible());
+ gl_->VerifySyncTokensCHROMIUM(sync_token_datas, arraysize(sync_token_datas));
EXPECT_TRUE(NoCommandsWritten());
EXPECT_EQ(GL_NO_ERROR, CheckError());
@@ -3898,6 +3895,67 @@ TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM) {
EXPECT_TRUE(sync_token.verified_flush());
}
+TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM_Sequence) {
+ // To verify sync tokens, the sync tokens must all be verified after
+ // CanWaitUnverifiedSyncTokens() are called. This test ensures the right
+ // sequence.
+ ExpectedMemoryInfo result =
+ GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+ EXPECT_CALL(*command_buffer(), OnFlush())
+ .WillRepeatedly(SetMemory(result.ptr, GLuint(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+
+ const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
+ const GLuint64 kCommandBufferId = 234u;
+ const GLuint64 kFenceSync1 = 123u;
+ const GLuint64 kFenceSync2 = 234u;
+ gpu::SyncToken sync_token1;
+ gpu::SyncToken sync_token2;
+ GLbyte* sync_token_datas[] = { sync_token1.GetData(), sync_token2.GetData() };
+
+ EXPECT_CALL(*gpu_control_, GetNamespaceID())
+ .WillRepeatedly(Return(kNamespaceId));
+ EXPECT_CALL(*gpu_control_, GetCommandBufferID())
+ .WillRepeatedly(Return(kCommandBufferId));
+ EXPECT_CALL(*gpu_control_, GetExtraCommandBufferData())
+ .WillRepeatedly(Return(0));
+
+ // Generate sync token 1.
+ EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync1))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync1))
+ .WillOnce(Return(true));
+ gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync1, sync_token1.GetData());
+ ASSERT_TRUE(sync_token1.HasData());
+ ASSERT_FALSE(sync_token1.verified_flush());
+
+ // Generate sync token 2.
+ EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync2))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync2))
+ .WillOnce(Return(true));
+ gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync2, sync_token2.GetData());
+ ASSERT_TRUE(sync_token2.HasData());
+ ASSERT_FALSE(sync_token2.verified_flush());
+
+ // Ensure proper sequence of checking and validating.
+ Sequence sequence;
+ EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(Pointee(sync_token1)))
+ .InSequence(sequence)
+ .WillOnce(Return(true));
+ EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(Pointee(sync_token2)))
+ .InSequence(sequence)
+ .WillOnce(Return(true));
+ EXPECT_CALL(*gpu_control_, EnsureWorkVisible())
+ .InSequence(sequence);
+ gl_->VerifySyncTokensCHROMIUM(sync_token_datas, arraysize(sync_token_datas));
+ EXPECT_TRUE(NoCommandsWritten());
+ EXPECT_EQ(GL_NO_ERROR, CheckError());
+
+ EXPECT_TRUE(sync_token1.verified_flush());
+ EXPECT_TRUE(sync_token2.verified_flush());
+}
+
TEST_F(GLES2ImplementationTest, WaitSyncTokenCHROMIUM) {
const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
const GLuint64 kCommandBufferId = 234u;