blob: abdbb253a3affe548a7072d85b152e429fb33abf [file] [log] [blame]
// Copyright 2017 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 "cc/ipc/copy_output_result_struct_traits.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace {
// 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_);
}
~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);
}
// 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();
}
private:
std::unique_ptr<cc::SingleReleaseCallback> release_callback_;
};
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>>::
bitmap(const std::unique_ptr<cc::CopyOutputResult>& result) {
static SkBitmap* null_bitmap = new SkBitmap();
if (!result->bitmap_)
return *null_bitmap;
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