diff options
author | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-22 11:17:40 +0000 |
---|---|---|
committer | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-22 11:17:40 +0000 |
commit | 755451eba1c47e1b169bb4e70903d073d131abea (patch) | |
tree | 8aa079f0e91902862a766a6710ebc7f63f841928 /cc | |
parent | 77a84826ef757c200e459d0d6985e796c7590014 (diff) | |
download | chromium_src-755451eba1c47e1b169bb4e70903d073d131abea.zip chromium_src-755451eba1c47e1b169bb4e70903d073d131abea.tar.gz chromium_src-755451eba1c47e1b169bb4e70903d073d131abea.tar.bz2 |
cc: Make ResourceProvider correctly handle transferring mailbox-created resources
For mailbox-created resources, the texture ID is created lazily, in lockForRead. If we use a delegating renderer, we won't lock it, so at the time we transfer it to the parent and back, we don't have a texture ID, and we shouldn't be producing/consuming. We still need to correctly handle the synchronization logic.
This change implements all this, and adds tests.
BUG=164095
Review URL: https://chromiumcodereview.appspot.com/12315046
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184089 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/resource_provider.cc | 17 | ||||
-rw-r--r-- | cc/resource_provider_unittest.cc | 113 |
2 files changed, 125 insertions, 5 deletions
diff --git a/cc/resource_provider.cc b/cc/resource_provider.cc index 0ac1e18..5de3149 100644 --- a/cc/resource_provider.cc +++ b/cc/resource_provider.cc @@ -760,8 +760,12 @@ void ResourceProvider::receiveFromParent(const TransferableResourceList& resourc DCHECK(resource->exported); resource->exported = false; DCHECK(resource->mailbox.Equals(it->mailbox)); - GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->glId)); - GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, it->mailbox.name)); + if (resource->glId) { + GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->glId)); + GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, it->mailbox.name)); + } else { + resource->mailbox = TextureMailbox(resource->mailbox.name(), resource->mailbox.callback(), resources.sync_point); + } if (resource->markedForDeletion) deleteResourceInternal(mapIterator); } @@ -791,8 +795,13 @@ bool ResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceI } else resource->mailbox = source->mailbox.name(); - GLC(context, context->bindTexture(GL_TEXTURE_2D, source->glId)); - GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, resource->mailbox.name)); + if (source->glId) { + GLC(context, context->bindTexture(GL_TEXTURE_2D, source->glId)); + GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, resource->mailbox.name)); + } else if (source->mailbox.sync_point()) { + GLC(context3d, context3d->waitSyncPoint(source->mailbox.sync_point())); + source->mailbox.ResetSyncPoint(); + } return true; } diff --git a/cc/resource_provider_unittest.cc b/cc/resource_provider_unittest.cc index 0058d11..ebca722 100644 --- a/cc/resource_provider_unittest.cc +++ b/cc/resource_provider_unittest.cc @@ -4,6 +4,7 @@ #include "cc/resource_provider.h" +#include "base/bind.h" #include "base/logging.h" #include "cc/output_surface.h" #include "cc/scoped_ptr_deque.h" @@ -83,8 +84,10 @@ public: // If the latest sync point the context has waited on is before the sync // point for when the mailbox was set, pretend we never saw that // produceTexture. - if (m_syncPointForMailbox[mailbox] < syncPoint) + if (m_syncPointForMailbox[mailbox] > syncPoint) { + NOTREACHED(); return scoped_ptr<Texture>(); + } return m_textures.take(mailbox); } @@ -564,6 +567,114 @@ TEST_P(ResourceProviderTest, DeleteTransferredResources) EXPECT_EQ(0u, childResourceProvider->numResources()); } +void ReleaseTextureMailbox(unsigned* releaseSyncPoint, unsigned syncPoint) { + *releaseSyncPoint = syncPoint; +} + +TEST_P(ResourceProviderTest, TransferMailboxResources) +{ + // Resource transfer is only supported with GL textures for now. + if (GetParam() != ResourceProvider::GLTexture) + return; + unsigned texture = context()->createTexture(); + context()->bindTexture(GL_TEXTURE_2D, texture); + uint8_t data[4] = {1, 2, 3, 4}; + context()->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data); + Mailbox mailbox; + context()->genMailboxCHROMIUM(mailbox.name); + context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); + unsigned syncPoint = context()->insertSyncPoint(); + + // All the logic below assumes that the sync points are all positive. + EXPECT_LT(0u, syncPoint); + + unsigned releaseSyncPoint = 0; + TextureMailbox::ReleaseCallback callback = base::Bind(ReleaseTextureMailbox, &releaseSyncPoint); + ResourceProvider::ResourceId resource = m_resourceProvider->createResourceFromTextureMailbox(TextureMailbox(mailbox, callback, syncPoint)); + EXPECT_EQ(1u, context()->textureCount()); + EXPECT_EQ(0u, releaseSyncPoint); + + { + // Transfer the resource, expect the sync points to be consistent. + ResourceProvider::ResourceIdArray resourceIdsToTransfer; + resourceIdsToTransfer.push_back(resource); + TransferableResourceList list; + m_resourceProvider->prepareSendToParent(resourceIdsToTransfer, &list); + EXPECT_LE(syncPoint, list.sync_point); + EXPECT_EQ(1u, list.resources.size()); + EXPECT_EQ(0u, memcmp(mailbox.name, list.resources[0].mailbox.name, sizeof(mailbox.name))); + EXPECT_EQ(0u, releaseSyncPoint); + + context()->waitSyncPoint(list.sync_point); + unsigned otherTexture = context()->createTexture(); + context()->bindTexture(GL_TEXTURE_2D, otherTexture); + context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); + uint8_t testData[4] = {0}; + context()->getPixels(gfx::Size(1, 1), GL_RGBA, testData); + EXPECT_EQ(0u, memcmp(data, testData, sizeof(data))); + context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); + context()->deleteTexture(otherTexture); + list.sync_point = context()->insertSyncPoint(); + EXPECT_LT(0u, list.sync_point); + + // Receive the resource, then delete it, expect the sync points to be consistent. + m_resourceProvider->receiveFromParent(list); + EXPECT_EQ(1u, context()->textureCount()); + EXPECT_EQ(0u, releaseSyncPoint); + + m_resourceProvider->deleteResource(resource); + EXPECT_LE(list.sync_point, releaseSyncPoint); + } + + + // We're going to do the same thing as above, but testing the case where we + // delete the resource before we receive it back. + syncPoint = releaseSyncPoint; + EXPECT_LT(0u, syncPoint); + releaseSyncPoint = 0; + resource = m_resourceProvider->createResourceFromTextureMailbox(TextureMailbox(mailbox, callback, syncPoint)); + EXPECT_EQ(1u, context()->textureCount()); + EXPECT_EQ(0u, releaseSyncPoint); + + { + // Transfer the resource, expect the sync points to be consistent. + ResourceProvider::ResourceIdArray resourceIdsToTransfer; + resourceIdsToTransfer.push_back(resource); + TransferableResourceList list; + m_resourceProvider->prepareSendToParent(resourceIdsToTransfer, &list); + EXPECT_LE(syncPoint, list.sync_point); + EXPECT_EQ(1u, list.resources.size()); + EXPECT_EQ(0u, memcmp(mailbox.name, list.resources[0].mailbox.name, sizeof(mailbox.name))); + EXPECT_EQ(0u, releaseSyncPoint); + + context()->waitSyncPoint(list.sync_point); + unsigned otherTexture = context()->createTexture(); + context()->bindTexture(GL_TEXTURE_2D, otherTexture); + context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); + uint8_t testData[4] = {0}; + context()->getPixels(gfx::Size(1, 1), GL_RGBA, testData); + EXPECT_EQ(0u, memcmp(data, testData, sizeof(data))); + context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); + context()->deleteTexture(otherTexture); + list.sync_point = context()->insertSyncPoint(); + EXPECT_LT(0u, list.sync_point); + + // Delete the resource, which shouldn't do anything. + m_resourceProvider->deleteResource(resource); + EXPECT_EQ(1u, context()->textureCount()); + EXPECT_EQ(0u, releaseSyncPoint); + + // Then receive the resource which should release the mailbox, expect the sync points to be consistent. + m_resourceProvider->receiveFromParent(list); + EXPECT_LE(list.sync_point, releaseSyncPoint); + } + + context()->waitSyncPoint(releaseSyncPoint); + context()->bindTexture(GL_TEXTURE_2D, texture); + context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); + context()->deleteTexture(texture); +} + class TextureStateTrackingContext : public TestWebGraphicsContext3D { public: MOCK_METHOD2(bindTexture, void(WGC3Denum target, WebGLId texture)); |