blob: 4e7ded9929c83f5e7433ac7c5da00434c27b52bb [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 "services/viz/public/cpp/compositing/copy_output_result_struct_traits.h"
#include "base/bind.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace {
// This class retains the SingleReleaseCallback of the CopyOutputResult that is
// being sent over mojo. A TextureReleaserPtr 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 TextureReleaserImpl : public viz::mojom::TextureReleaser {
public:
explicit TextureReleaserImpl(
std::unique_ptr<viz::SingleReleaseCallback> release_callback)
: release_callback_(std::move(release_callback)) {}
// mojom::TextureReleaser implementation:
void Release(const gpu::SyncToken& sync_token, bool is_lost) override {
release_callback_->Run(sync_token, is_lost);
}
private:
std::unique_ptr<viz::SingleReleaseCallback> release_callback_;
};
void Release(viz::mojom::TextureReleaserPtr ptr,
const gpu::SyncToken& sync_token,
bool is_lost) {
ptr->Release(sync_token, is_lost);
}
} // namespace
namespace mojo {
// static
viz::mojom::CopyOutputResultFormat
EnumTraits<viz::mojom::CopyOutputResultFormat, viz::CopyOutputResult::Format>::
ToMojom(viz::CopyOutputResult::Format format) {
switch (format) {
case viz::CopyOutputResult::Format::RGBA_BITMAP:
return viz::mojom::CopyOutputResultFormat::RGBA_BITMAP;
case viz::CopyOutputResult::Format::RGBA_TEXTURE:
return viz::mojom::CopyOutputResultFormat::RGBA_TEXTURE;
case viz::CopyOutputResult::Format::I420_PLANES:
break; // Not intended for transport across service boundaries.
}
NOTREACHED();
return viz::mojom::CopyOutputResultFormat::RGBA_BITMAP;
}
// static
bool EnumTraits<viz::mojom::CopyOutputResultFormat,
viz::CopyOutputResult::Format>::
FromMojom(viz::mojom::CopyOutputResultFormat input,
viz::CopyOutputResult::Format* out) {
switch (input) {
case viz::mojom::CopyOutputResultFormat::RGBA_BITMAP:
*out = viz::CopyOutputResult::Format::RGBA_BITMAP;
return true;
case viz::mojom::CopyOutputResultFormat::RGBA_TEXTURE:
*out = viz::CopyOutputResult::Format::RGBA_TEXTURE;
return true;
}
return false;
}
// static
viz::CopyOutputResult::Format
StructTraits<viz::mojom::CopyOutputResultDataView,
std::unique_ptr<viz::CopyOutputResult>>::
format(const std::unique_ptr<viz::CopyOutputResult>& result) {
return result->format();
}
// static
const gfx::Rect& StructTraits<viz::mojom::CopyOutputResultDataView,
std::unique_ptr<viz::CopyOutputResult>>::
rect(const std::unique_ptr<viz::CopyOutputResult>& result) {
return result->rect();
}
// static
const SkBitmap& StructTraits<viz::mojom::CopyOutputResultDataView,
std::unique_ptr<viz::CopyOutputResult>>::
bitmap(const std::unique_ptr<viz::CopyOutputResult>& result) {
// This will return a non-drawable bitmap if the result was not
// RGBA_BITMAP or if the result is empty.
return result->AsSkBitmap();
}
// static
base::Optional<gpu::Mailbox>
StructTraits<viz::mojom::CopyOutputResultDataView,
std::unique_ptr<viz::CopyOutputResult>>::
mailbox(const std::unique_ptr<viz::CopyOutputResult>& result) {
if (result->format() != viz::CopyOutputResult::Format::RGBA_TEXTURE ||
result->IsEmpty()) {
return base::nullopt;
}
return result->GetTextureResult()->mailbox;
}
// static
base::Optional<gpu::SyncToken>
StructTraits<viz::mojom::CopyOutputResultDataView,
std::unique_ptr<viz::CopyOutputResult>>::
sync_token(const std::unique_ptr<viz::CopyOutputResult>& result) {
if (result->format() != viz::CopyOutputResult::Format::RGBA_TEXTURE ||
result->IsEmpty()) {
return base::nullopt;
}
return result->GetTextureResult()->sync_token;
}
// static
base::Optional<gfx::ColorSpace>
StructTraits<viz::mojom::CopyOutputResultDataView,
std::unique_ptr<viz::CopyOutputResult>>::
color_space(const std::unique_ptr<viz::CopyOutputResult>& result) {
if (result->format() != viz::CopyOutputResult::Format::RGBA_TEXTURE ||
result->IsEmpty()) {
return base::nullopt;
}
return result->GetTextureResult()->color_space;
}
// static
viz::mojom::TextureReleaserPtr
StructTraits<viz::mojom::CopyOutputResultDataView,
std::unique_ptr<viz::CopyOutputResult>>::
releaser(const std::unique_ptr<viz::CopyOutputResult>& result) {
if (result->format() != viz::CopyOutputResult::Format::RGBA_TEXTURE)
return nullptr;
viz::mojom::TextureReleaserPtr releaser;
MakeStrongBinding(
std::make_unique<TextureReleaserImpl>(result->TakeTextureOwnership()),
MakeRequest(&releaser));
return releaser;
}
// static
bool StructTraits<viz::mojom::CopyOutputResultDataView,
std::unique_ptr<viz::CopyOutputResult>>::
Read(viz::mojom::CopyOutputResultDataView data,
std::unique_ptr<viz::CopyOutputResult>* out_p) {
// First read into local variables, and then instantiate an appropriate
// implementation of viz::CopyOutputResult.
viz::CopyOutputResult::Format format;
gfx::Rect rect;
// TODO(crbug.com/967856): Removed detailed logging for deserialization
// failures after bug is fixed.
if (!data.ReadFormat(&format)) {
LOG(ERROR) << "CopyOutputResult: Failed to read |format|";
return false;
}
if (!data.ReadRect(&rect)) {
LOG(ERROR) << "CopyOutputResult: Failed to read |rect|.";
return false;
}
if (rect.IsEmpty()) {
// An empty rect implies an empty result.
*out_p = std::make_unique<viz::CopyOutputResult>(format, gfx::Rect());
return true;
}
switch (format) {
case viz::CopyOutputResult::Format::RGBA_BITMAP: {
SkBitmap bitmap;
if (!data.ReadBitmap(&bitmap) || !bitmap.readyToDraw()) {
LOG(ERROR) << "CopyOutputResult: Failed to read |bitmap|";
return false;
}
*out_p = std::make_unique<viz::CopyOutputSkBitmapResult>(
rect, std::move(bitmap));
return true;
}
case viz::CopyOutputResult::Format::RGBA_TEXTURE: {
base::Optional<gpu::Mailbox> mailbox;
if (!data.ReadMailbox(&mailbox) || !mailbox) {
LOG(ERROR) << "CopyOutputResult: Failed to read |mailbox|";
return false;
}
base::Optional<gpu::SyncToken> sync_token;
if (!data.ReadSyncToken(&sync_token) || !sync_token) {
LOG(ERROR) << "CopyOutputResult: Failed to read |sync_token|";
return false;
}
base::Optional<gfx::ColorSpace> color_space;
if (!data.ReadColorSpace(&color_space) || !color_space) {
LOG(ERROR) << "CopyOutputResult: Failed to read |color_space|";
return false;
}
if (mailbox->IsZero()) {
// Returns an empty result.
*out_p = std::make_unique<viz::CopyOutputResult>(
viz::CopyOutputResult::Format::RGBA_TEXTURE, gfx::Rect());
return true;
}
viz::mojom::TextureReleaserPtr releaser =
data.TakeReleaser<viz::mojom::TextureReleaserPtr>();
if (!releaser) {
LOG(ERROR) << "CopyOutputResult: Failed to take |releaser|";
return false; // Illegal to provide texture without Releaser.
}
// Returns a result with a SingleReleaseCallback that will return
// here and proxy the callback over mojo to the CopyOutputResult's
// origin via the TextureReleaserPtr.
*out_p = std::make_unique<viz::CopyOutputTextureResult>(
rect, *mailbox, *sync_token, *color_space,
viz::SingleReleaseCallback::Create(
base::Bind(&Release, base::Passed(&releaser))));
return true;
}
case viz::CopyOutputResult::Format::I420_PLANES:
break; // Not intended for transport across service boundaries.
}
NOTREACHED();
return false;
}
} // namespace mojo