Index: cc/ipc/copy_output_result_struct_traits.cc |
diff --git a/cc/ipc/copy_output_result_struct_traits.cc b/cc/ipc/copy_output_result_struct_traits.cc |
index 0398fe115cd52463b56fbf2a1a1540d3d96b2935..abdbb253a3affe548a7072d85b152e429fb33abf 100644 |
--- a/cc/ipc/copy_output_result_struct_traits.cc |
+++ b/cc/ipc/copy_output_result_struct_traits.cc |
@@ -4,30 +4,53 @@ |
#include "cc/ipc/copy_output_result_struct_traits.h" |
-namespace mojo { |
+#include "mojo/public/cpp/bindings/strong_binding.h" |
-// static |
-bool StructTraits<cc::mojom::CopyOutputResultDataView, |
- std::unique_ptr<cc::CopyOutputResult>>:: |
- Read(cc::mojom::CopyOutputResultDataView data, |
- std::unique_ptr<cc::CopyOutputResult>* out_p) { |
- auto result = cc::CopyOutputResult::CreateEmptyResult(); |
+namespace { |
- if (!data.ReadSize(&result->size_)) |
- return false; |
+// This class retains the release_callback_ of the CopyOutputResult that is |
+// being sent over mojo. A TextureMailboxReleaserPtr that talks to this impl |
+// object will be sent over mojo instead of the release_callback_ (which is not |
+// serializable). Once the client calls Release, the release_callback_ will be |
+// called. An object of this class will remain alive until the MessagePipe |
+// attached to it goes away (i.e. StrongBinding is used). |
+class TextureMailboxReleaserImpl : public cc::mojom::TextureMailboxReleaser { |
+ public: |
+ TextureMailboxReleaserImpl( |
+ std::unique_ptr<cc::SingleReleaseCallback> release_callback) |
+ : release_callback_(std::move(release_callback)) { |
+ DCHECK(release_callback_); |
+ } |
- result->bitmap_ = base::MakeUnique<SkBitmap>(); |
- if (!data.ReadBitmap(result->bitmap_.get())) |
- return false; |
+ ~TextureMailboxReleaserImpl() override { |
+ // If the client fails to call Release, we should do it ourselves because |
+ // release_callback_ will fail if it's never called. |
+ if (release_callback_) |
+ release_callback_->Run(gpu::SyncToken(), true); |
+ } |
- if (!data.ReadTextureMailbox(&result->texture_mailbox_)) |
- return false; |
+ // mojom::TextureMailboxReleaser implementation: |
+ void Release(const gpu::SyncToken& sync_token, bool is_lost) override { |
+ if (!release_callback_) |
+ return; |
+ release_callback_->Run(sync_token, is_lost); |
+ release_callback_.reset(); |
+ } |
- *out_p = std::move(result); |
+ private: |
+ std::unique_ptr<cc::SingleReleaseCallback> release_callback_; |
+}; |
- return true; |
+void Release(cc::mojom::TextureMailboxReleaserPtr ptr, |
+ const gpu::SyncToken& sync_token, |
+ bool is_lost) { |
+ ptr->Release(sync_token, is_lost); |
} |
+} // namespace |
+ |
+namespace mojo { |
+ |
// static |
const SkBitmap& StructTraits<cc::mojom::CopyOutputResultDataView, |
std::unique_ptr<cc::CopyOutputResult>>:: |
@@ -38,4 +61,74 @@ const SkBitmap& StructTraits<cc::mojom::CopyOutputResultDataView, |
return *result->bitmap_; |
} |
+// static |
+cc::mojom::TextureMailboxReleaserPtr |
+StructTraits<cc::mojom::CopyOutputResultDataView, |
+ std::unique_ptr<cc::CopyOutputResult>>:: |
+ releaser(const std::unique_ptr<cc::CopyOutputResult>& result) { |
+ if (!result->release_callback_) |
+ return {}; |
+ cc::mojom::TextureMailboxReleaserPtr releaser; |
+ auto impl = base::MakeUnique<TextureMailboxReleaserImpl>( |
+ std::move(result->release_callback_)); |
+ MakeStrongBinding(std::move(impl), MakeRequest(&releaser)); |
+ return releaser; |
+} |
+ |
+// static |
+bool StructTraits<cc::mojom::CopyOutputResultDataView, |
+ std::unique_ptr<cc::CopyOutputResult>>:: |
+ Read(cc::mojom::CopyOutputResultDataView data, |
+ std::unique_ptr<cc::CopyOutputResult>* out_p) { |
+ // We first read into local variables and then call the appropriate |
+ // constructor of cc::CopyOutputResult. |
+ gfx::Size size; |
+ auto bitmap = base::MakeUnique<SkBitmap>(); |
+ cc::TextureMailbox texture_mailbox; |
+ std::unique_ptr<cc::SingleReleaseCallback> release_callback; |
+ |
+ if (!data.ReadSize(&size)) |
+ return false; |
+ |
+ if (!data.ReadBitmap(bitmap.get())) |
+ return false; |
+ |
+ if (!data.ReadTextureMailbox(&texture_mailbox)) |
+ return false; |
+ |
+ auto releaser = data.TakeReleaser<cc::mojom::TextureMailboxReleaserPtr>(); |
+ if (releaser) { |
+ // CopyOutputResult does not have a TextureMailboxReleaserPtr member. |
+ // We use base::Bind to turn TextureMailboxReleaser::Release into a |
+ // ReleaseCallback. |
+ release_callback = cc::SingleReleaseCallback::Create( |
+ base::Bind(Release, base::Passed(&releaser))); |
+ } |
+ |
+ // Empty result. |
+ if (bitmap->isNull() && !texture_mailbox.IsTexture()) { |
+ *out_p = cc::CopyOutputResult::CreateEmptyResult(); |
+ return true; |
+ } |
+ |
+ // Bitmap result. |
+ if (!bitmap->isNull()) { |
+ // We can't have both a bitmap and a texture. |
+ if (texture_mailbox.IsTexture()) |
+ return false; |
+ *out_p = cc::CopyOutputResult::CreateBitmapResult(std::move(bitmap)); |
+ return true; |
+ } |
+ |
+ // Texture result. |
+ DCHECK(texture_mailbox.IsTexture()); |
+ if (size.IsEmpty()) |
+ return false; |
+ if (!release_callback) |
+ return false; |
+ *out_p = cc::CopyOutputResult::CreateTextureResult( |
+ size, texture_mailbox, std::move(release_callback)); |
+ return true; |
+} |
+ |
} // namespace mojo |